feat: release version 1.0.8

This commit is contained in:
2026-08-29 23:49:56 +09:00
parent 3dc19a9c23
commit a06cacb91c
48 changed files with 9079 additions and 922 deletions
+46 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"masterDataVersion": "71e11fbd082eec83d10cff35da7179cbaf319097f0021aa5747fe5a5392b549c",
"masterDataVersion": "fbca8c670e074558b24708bf163fff446a614f709afa9d1784395a15444121b0",
"members": [
{
"id": "chr-00001",
@@ -329,6 +329,11 @@
],
"models": {
"tree-model-001": [
{
"groupId": "G-024",
"x": -1,
"y": -10
},
{
"groupId": "G-022",
"x": -1,
@@ -1091,6 +1096,11 @@
}
],
"tree-model-002": [
{
"groupId": "G-024",
"x": -1,
"y": -10
},
{
"groupId": "G-022",
"x": -1,
@@ -1853,6 +1863,11 @@
}
],
"tree-model-003": [
{
"groupId": "G-024",
"x": -1,
"y": -10
},
{
"groupId": "G-022",
"x": -1,
@@ -2615,6 +2630,11 @@
}
],
"tree-model-004": [
{
"groupId": "G-024",
"x": -1,
"y": -10
},
{
"groupId": "G-022",
"x": -1,
@@ -9024,6 +9044,31 @@
}
}
],
"G-024": [
{
"number": 1,
"characterIds": [],
"grade": 1,
"type": "all_member",
"skillTreePointCost": 3,
"consumptions": [
{
"resourceType": "ResourceType_RESOURCE_TYPE_ITEM",
"resourceId": "item-skill_tree_allmember-1",
"quantity": "160"
}
],
"viewConditionGroupId": "cd-player_level-30",
"effect": {
"id": "skill_tree_effect-mini_game_reward_quantity_up_permil_up-5-skill_tree_effect_target-all-chase",
"type": "mini_game_reward_quantity_up_permil_up",
"value": 5,
"targetId": "skill_tree_effect_target-all",
"trigger": "always",
"description": " 어둠 속 추격의 획득 보상량이 [value/10]% UP"
}
}
],
"R-001": [
{
"number": 1,
+613 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"masterDataVersion": "71e11fbd082eec83d10cff35da7179cbaf319097f0021aa5747fe5a5392b549c",
"masterDataVersion": "fbca8c670e074558b24708bf163fff446a614f709afa9d1784395a15444121b0",
"cards": [
{
"id": "card-00001-5-uniq-0000-00",
@@ -1316,6 +1316,167 @@
}
}
},
{
"id": "card-00006-5-uniq-0074-00",
"characterId": "chr-00006",
"rarity": 5,
"type": "큐트",
"name": "시라카미 후부키",
"versionName": "수영복",
"generation": "hololive 1기생 / GAMERS",
"highestStat": "센스",
"power": {
"maxLevel": 80,
"statsAtMaxLevel": {
"performance": 6184,
"technique": 6983,
"sense": 10345
}
},
"details": {
"title": "물가에서 매료하는 twinkle",
"passive": [
{
"level": 1,
"description": "[attribute=cute]큐트 타입[/attribute] 2명의 스코어 서포트 효과 8% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
},
{
"level": 2,
"description": "[attribute=cute]큐트 타입[/attribute] 2명의 스코어 서포트 효과 [highlight]11[/highlight]% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
}
],
"active": [
{
"level": 1,
"description": "35초마다 중간 확률로 13초 동안 스코어가 95% UP ",
"coolTimeSeconds": 35,
"probabilityPercent": 46,
"durationSeconds": 13,
"condition": "",
"effect": "스코어가 95% UP"
},
{
"level": 2,
"description": "35초마다 중간 확률로 13초 동안 스코어가 [highlight]115[/highlight]% UP ",
"coolTimeSeconds": 35,
"probabilityPercent": 46,
"durationSeconds": 13,
"condition": "",
"effect": "스코어가 115% UP"
}
],
"special": [
{
"level": 1,
"description": "12초 동안 스코어 서포트 효과 110% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 110%"
},
{
"level": 2,
"description": "12초 동안 스코어 서포트 효과 [highlight]135[/highlight]% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 135%"
}
],
"connect": [
{
"level": 1,
"description": "범위 내의 holo멤버 보드 효과를 85% UP",
"effectPermilUp": 850,
"extent": [
{
"x": 0,
"y": -2
},
{
"x": -1,
"y": -1
},
{
"x": 0,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": -2,
"y": 0
},
{
"x": -1,
"y": 1
},
{
"x": 0,
"y": 1
},
{
"x": 0,
"y": 2
}
]
},
{
"level": 2,
"description": "범위 내의 holo멤버 보드 효과를 [highlight]135[/highlight]% UP",
"effectPermilUp": 1350,
"extent": [
{
"x": 0,
"y": -2
},
{
"x": -1,
"y": -1
},
{
"x": 0,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": -2,
"y": 0
},
{
"x": -1,
"y": 1
},
{
"x": 0,
"y": 1
},
{
"x": 0,
"y": 2
}
]
}
],
"costume": {
"name": "1UP 스포티",
"description": "[attribute=cute]큐트 타입[/attribute] 2명 이상이면 전원의 센스가 130% UP "
}
}
},
{
"id": "card-00007-5-uniq-0008-00",
"characterId": "chr-00007",
@@ -2275,6 +2436,151 @@
}
}
},
{
"id": "card-00014-5-uniq-0075-00",
"characterId": "chr-00014",
"rarity": 5,
"type": "퓨어",
"name": "오오카미 미오",
"versionName": "수영복",
"generation": "hololive 게이머즈",
"highestStat": "테크닉",
"power": {
"maxLevel": 80,
"statsAtMaxLevel": {
"performance": 6184,
"technique": 10345,
"sense": 6983
}
},
"details": {
"title": "나른한 여름날의 Wolf Heart",
"passive": [
{
"level": 1,
"description": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면 [attribute=pure]퓨어 타입[/attribute] 2명의 테크닉이 32% UP ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
},
{
"level": 2,
"description": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면 [attribute=pure]퓨어 타입[/attribute] 2명의 테크닉이 [highlight]43[/highlight]% UP ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
}
],
"active": [
{
"level": 1,
"description": "23초마다 중간 확률로 8초 동안 스코어가 100% UP ",
"coolTimeSeconds": 23,
"probabilityPercent": 46,
"durationSeconds": 8,
"condition": "",
"effect": "스코어가 100% UP"
},
{
"level": 2,
"description": "23초마다 중간 확률로 8초 동안 스코어가 [highlight]120[/highlight]% UP ",
"coolTimeSeconds": 23,
"probabilityPercent": 46,
"durationSeconds": 8,
"condition": "",
"effect": "스코어가 120% UP"
}
],
"special": [
{
"level": 1,
"description": "12초 동안 스코어 서포트 효과 110% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 110%"
},
{
"level": 2,
"description": "12초 동안 스코어 서포트 효과 [highlight]135[/highlight]% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 135%"
}
],
"connect": [
{
"level": 1,
"description": "범위 내의 holo멤버 보드 효과를 110% UP",
"effectPermilUp": 1100,
"extent": [
{
"x": -1,
"y": -1
},
{
"x": 0,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": 1,
"y": 0
},
{
"x": -1,
"y": 1
},
{
"x": 0,
"y": 1
}
]
},
{
"level": 2,
"description": "범위 내의 holo멤버 보드 효과를 [highlight]160[/highlight]% UP",
"effectPermilUp": 1600,
"extent": [
{
"x": -1,
"y": -1
},
{
"x": 0,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": 1,
"y": 0
},
{
"x": -1,
"y": 1
},
{
"x": 0,
"y": 1
}
]
}
],
"costume": {
"name": "물가의 HIGH SCORE",
"description": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면 전원의 테크닉이 130% UP "
}
}
},
{
"id": "card-00016-5-uniq-0014-00",
"characterId": "chr-00016",
@@ -2404,6 +2710,167 @@
}
}
},
{
"id": "card-00016-5-uniq-0076-00",
"characterId": "chr-00016",
"rarity": 5,
"type": "해피",
"name": "네코마타 오카유",
"versionName": "수영복",
"generation": "hololive 게이머즈",
"highestStat": "퍼포먼스",
"power": {
"maxLevel": 80,
"statsAtMaxLevel": {
"performance": 10132,
"technique": 7116,
"sense": 6315
}
},
"details": {
"title": "파라솔 아래 리버티 캣",
"passive": [
{
"level": 1,
"description": "GAMERS2명의 퍼포먼스가 32% UP ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
},
{
"level": 2,
"description": "GAMERS2명의 퍼포먼스가 [highlight]43[/highlight]% UP ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
}
],
"active": [
{
"level": 1,
"description": "28초마다 높은 확률로 10초 동안 스코어가 95% UP ",
"coolTimeSeconds": 28,
"probabilityPercent": 55,
"durationSeconds": 10,
"condition": "",
"effect": "스코어가 95% UP"
},
{
"level": 2,
"description": "28초마다 높은 확률로 10초 동안 스코어가 [highlight]110[/highlight]% UP ",
"coolTimeSeconds": 28,
"probabilityPercent": 55,
"durationSeconds": 10,
"condition": "",
"effect": "스코어가 110% UP"
}
],
"special": [
{
"level": 1,
"description": "11초 동안 스코어 서포트 효과 110% GAMERS(이)가 2명 이상이면 스킬 발동률이 40% UP",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 11,
"condition": "GAMERS(이)가 2명 이상이면",
"effect": "스코어 서포트 효과 110% 스킬 발동률이 40% UP"
},
{
"level": 2,
"description": "11초 동안 스코어 서포트 효과 [highlight]130[/highlight]% GAMERS(이)가 2명 이상이면 스킬 발동률이 [highlight]50[/highlight]% UP",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 11,
"condition": "GAMERS(이)가 2명 이상이면",
"effect": "스코어 서포트 효과 130% 스킬 발동률이 50% UP"
}
],
"connect": [
{
"level": 1,
"description": "범위 내의 holo멤버 보드 효과를 85% UP",
"effectPermilUp": 850,
"extent": [
{
"x": 0,
"y": -2
},
{
"x": 0,
"y": -1
},
{
"x": 1,
"y": -1
},
{
"x": 1,
"y": 0
},
{
"x": 2,
"y": 0
},
{
"x": 0,
"y": 1
},
{
"x": 1,
"y": 1
},
{
"x": 0,
"y": 2
}
]
},
{
"level": 2,
"description": "범위 내의 holo멤버 보드 효과를 [highlight]135[/highlight]% UP",
"effectPermilUp": 1350,
"extent": [
{
"x": 0,
"y": -2
},
{
"x": 0,
"y": -1
},
{
"x": 1,
"y": -1
},
{
"x": 1,
"y": 0
},
{
"x": 2,
"y": 0
},
{
"x": 0,
"y": 1
},
{
"x": 1,
"y": 1
},
{
"x": 0,
"y": 2
}
]
}
],
"costume": {
"name": "바닷바람의 캣워크",
"description": "GAMERS(이)가 2명 이상이면 전원의 퍼포먼스가 135% UP "
}
}
},
{
"id": "card-00017-5-uniq-0015-00",
"characterId": "chr-00017",
@@ -2541,6 +3008,151 @@
}
}
},
{
"id": "card-00017-5-uniq-0077-00",
"characterId": "chr-00017",
"rarity": 5,
"type": "퓨어",
"name": "이누가미 코로네",
"versionName": "수영복",
"generation": "hololive 게이머즈",
"highestStat": "테크닉",
"power": {
"maxLevel": 80,
"statsAtMaxLevel": {
"performance": 6315,
"technique": 10132,
"sense": 7116
}
},
"details": {
"title": "밀림을 누비는 와일드 서머!",
"passive": [
{
"level": 1,
"description": "[attribute=pure]퓨어 타입[/attribute] 2명의 스코어 서포트 효과 8% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
},
{
"level": 2,
"description": "[attribute=pure]퓨어 타입[/attribute] 2명의 스코어 서포트 효과 [highlight]11[/highlight]% ",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": null
}
],
"active": [
{
"level": 1,
"description": "32초마다 높은 확률로 11초 동안 스코어가 50% UP [attribute=pure]퓨어 타입[/attribute] 2명 이상이면 스코어가 100% UP ",
"coolTimeSeconds": 32,
"probabilityPercent": 55,
"durationSeconds": 11,
"condition": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면",
"effect": "스코어가 100% UP"
},
{
"level": 2,
"description": "32초마다 높은 확률로 11초 동안 스코어가 [highlight]60[/highlight]% UP [attribute=pure]퓨어 타입[/attribute] 2명 이상이면 스코어가 [highlight]120[/highlight]% UP ",
"coolTimeSeconds": 32,
"probabilityPercent": 55,
"durationSeconds": 11,
"condition": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면",
"effect": "스코어가 120% UP"
}
],
"special": [
{
"level": 1,
"description": "12초 동안 스코어 서포트 효과 100% 스킬 발동률이 35% UP",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 100% 스킬 발동률이 35% UP"
},
{
"level": 2,
"description": "12초 동안 스코어 서포트 효과 [highlight]120[/highlight]% 스킬 발동률이 [highlight]40[/highlight]% UP",
"coolTimeSeconds": null,
"probabilityPercent": null,
"durationSeconds": 12,
"condition": "",
"effect": "스코어 서포트 효과 120% 스킬 발동률이 40% UP"
}
],
"connect": [
{
"level": 1,
"description": "범위 내의 holo멤버 보드 효과를 110% UP",
"effectPermilUp": 1100,
"extent": [
{
"x": 0,
"y": -1
},
{
"x": 1,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": 1,
"y": 0
},
{
"x": 0,
"y": 1
},
{
"x": 1,
"y": 1
}
]
},
{
"level": 2,
"description": "범위 내의 holo멤버 보드 효과를 [highlight]160[/highlight]% UP",
"effectPermilUp": 1600,
"extent": [
{
"x": 0,
"y": -1
},
{
"x": 1,
"y": -1
},
{
"x": -1,
"y": 0
},
{
"x": 1,
"y": 0
},
{
"x": 0,
"y": 1
},
{
"x": 1,
"y": 1
}
]
}
],
"costume": {
"name": "줄무늬 임팩트",
"description": "[attribute=pure]퓨어 타입[/attribute] 2명 이상이면 전원의 테크닉이 80% UP [attribute=pure]퓨어 타입[/attribute] 2명 이상이면 전원의 스코어 서포트 효과 25%"
}
}
},
{
"id": "card-00019-5-uniq-0016-00",
"characterId": "chr-00019",
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"masterDataVersion": "71e11fbd082eec83d10cff35da7179cbaf319097f0021aa5747fe5a5392b549c",
"maxCount": 28,
"masterDataVersion": "fbca8c670e074558b24708bf163fff446a614f709afa9d1784395a15444121b0",
"maxCount": 29,
"effects": [
{
"count": 1,
+1
View File
@@ -6,6 +6,7 @@ export type SongChartSummary = {
difficulty: string;
difficultyLevel?: number | null;
scoreCalibrationSource?: 'measured' | 'local-estimated-v1' | string;
releaseTime?: number | null;
};
export type SongOption = {
+6 -4
View File
@@ -6,11 +6,13 @@ export const SONG_RELEASE_TIMES: Readonly<Record<string, number>> = {
m0336: 1_787_655_600_000
};
export function isSongReleased(songId: string, now = Date.now()): boolean {
const releaseTime = SONG_RELEASE_TIMES[songId];
export function isSongReleased(songId: string, now = Date.now(), catalogReleaseTime?: number | null): boolean {
const releaseTime = typeof catalogReleaseTime === 'number' && Number.isFinite(catalogReleaseTime)
? catalogReleaseTime
: SONG_RELEASE_TIMES[songId];
return releaseTime === undefined || now >= releaseTime;
}
export function releasedSongCharts<T extends { songId: string }>(charts: readonly T[], now = Date.now()): T[] {
return charts.filter((chart) => isSongReleased(chart.songId, now));
export function releasedSongCharts<T extends { songId: string; releaseTime?: number | null }>(charts: readonly T[], now = Date.now()): T[] {
return charts.filter((chart) => isSongReleased(chart.songId, now, chart.releaseTime));
}
+11
View File
@@ -30,3 +30,14 @@ test('채보 목록에서 공개되지 않은 악곡의 모든 난이도를 제
assert.deepEqual(releasedSongCharts(charts, SONG_RELEASE_TIMES.m0332 - 1), [charts[0]]);
assert.deepEqual(releasedSongCharts(charts, SONG_RELEASE_TIMES.m0332), charts);
});
test('채보 카탈로그의 HolodoriDB 공개 시각을 수동 목록보다 우선한다', () => {
const releaseTime = Date.parse('2026-08-30T00:00:00+09:00');
const charts = [
{ songId: 'm0359', difficulty: 'expert', releaseTime },
{ songId: 'm0359', difficulty: 'hard', releaseTime }
];
assert.deepEqual(releasedSongCharts(charts, releaseTime - 1), []);
assert.deepEqual(releasedSongCharts(charts, releaseTime), charts);
});