Compare commits
37 Commits
9090086a47
...
c303d3040d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c303d3040d | ||
|
|
c7dfd43daa | ||
|
|
9147ab0ec7 | ||
|
|
4438e81e37 | ||
|
|
2cb8c271a8 | ||
|
|
0ceab721e9 | ||
|
|
d877febcb8 | ||
|
|
8a35f8c40b | ||
|
|
6ed61ea9f1 | ||
|
|
7abdfe27cb | ||
|
|
9bec1df52f | ||
|
|
9043e20646 | ||
|
|
1420c60486 | ||
|
|
44da54c418 | ||
|
|
61a9133855 | ||
|
|
d661b6f44c | ||
|
|
3f784f4294 | ||
|
|
faa8c0e6dd | ||
|
|
34de3d53ad | ||
|
|
8f07afce83 | ||
|
|
95b8f39ea5 | ||
|
|
141f34f817 | ||
|
|
c02991a5c2 | ||
|
|
d14a0be2c8 | ||
|
|
87d0001569 | ||
|
|
8dbd52da54 | ||
|
|
34ed8788a4 | ||
|
|
a71bf6c62b | ||
|
|
83298a2d47 | ||
|
|
a5e4f35c32 | ||
|
|
0da8ebe1c1 | ||
|
|
f66d20e039 | ||
|
|
c23c56d46c | ||
|
|
0b41474968 | ||
|
|
40b0de1d51 | ||
|
|
7ec4892d73 | ||
|
|
f2a1263198 |
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
{"data_headers":{"sid":"079f239bb83de281ebc6b2f68dbb2cd11779683743","short_udid":411054851,"viewer_id":906243102,"servertime":1779683743,"result_code":1},"data":[{"mission_name":"Clear all Dragoncraft and Portalcraft puzzles puzzles in the Special Round","require_number":"2","campaign_commence_time":1725670800,"reward_list":[{"reward_type":"4","reward_detail_id":"90001","reward_number":"1"}],"order_id":"5","total_count":"0","is_achieved":false},{"mission_name":"Clear all Forestcraft, Shadowcraft and Bloodcraft puzzles in the Special Round","require_number":"3","campaign_commence_time":1722646800,"reward_list":[{"reward_type":"4","reward_detail_id":"90001","reward_number":"1"}],"order_id":"4","total_count":"0","is_achieved":false},{"mission_name":"Clear all Swordcraft, Runecraft and Havencraft puzzles in the Special Round","require_number":"3","campaign_commence_time":1720227600,"reward_list":[{"reward_type":"4","reward_detail_id":"90001","reward_number":"1"}],"order_id":"3","total_count":"0","is_achieved":false},{"mission_name":"Clear all Special Round puzzles","require_number":"8","campaign_commence_time":1720227600,"reward_list":[{"reward_type":"7","reward_detail_id":"400004315","reward_number":"1"}],"order_id":"2","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 15 puzzles","require_number":"3","campaign_commence_time":1716598800,"reward_list":[{"reward_type":"7","reward_detail_id":"400004314","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 14 puzzles","require_number":"3","campaign_commence_time":1711760400,"reward_list":[{"reward_type":"6","reward_detail_id":"3065004","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 13 puzzles","require_number":"3","campaign_commence_time":1708736400,"reward_list":[{"reward_type":"7","reward_detail_id":"400004313","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 12 puzzles","require_number":"3","campaign_commence_time":1703898000,"reward_list":[{"reward_type":"6","reward_detail_id":"3074009","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 11 puzzles","require_number":"3","campaign_commence_time":1700269200,"reward_list":[{"reward_type":"6","reward_detail_id":"3074008","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 10 puzzles","require_number":"3","campaign_commence_time":1692406800,"reward_list":[{"reward_type":"6","reward_detail_id":"3074007","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 9 puzzles","require_number":"3","campaign_commence_time":1688173200,"reward_list":[{"reward_type":"6","reward_detail_id":"3074006","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 8 puzzles","require_number":"3","campaign_commence_time":1684544400,"reward_list":[{"reward_type":"6","reward_detail_id":"3074005","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 7 puzzles","require_number":"3","campaign_commence_time":1677286800,"reward_list":[{"reward_type":"6","reward_detail_id":"3074004","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 6 puzzles","require_number":"3","campaign_commence_time":1672448400,"reward_list":[{"reward_type":"6","reward_detail_id":"3074003","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 5 puzzles","require_number":"3","campaign_commence_time":1669424400,"reward_list":[{"reward_type":"6","reward_detail_id":"3074002","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 4 puzzles","require_number":"3","campaign_commence_time":1660959000,"reward_list":[{"reward_type":"6","reward_detail_id":"3074001","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 3 puzzles","require_number":"3","campaign_commence_time":1656725400,"reward_list":[{"reward_type":"7","reward_detail_id":"400004105","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 2 puzzles","require_number":"3","campaign_commence_time":1653096600,"reward_list":[{"reward_type":"7","reward_detail_id":"400004104","reward_number":"1"}],"order_id":"1","total_count":"0","is_achieved":false},{"mission_name":"Clear all Round 1 puzzles","require_number":"3","campaign_commence_time":1651282200,"reward_list":[{"reward_type":"10","reward_detail_id":"3704","reward_number":"1"}],"order_id":"1","total_count":"3","is_achieved":true}]}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,484 +0,0 @@
|
|||||||
{
|
|
||||||
"data_headers": {
|
|
||||||
"sid": "ac631c29b5f5d07ed5fb6712ad8623c31779553958",
|
|
||||||
"short_udid": 411054851,
|
|
||||||
"viewer_id": 906243102,
|
|
||||||
"servertime": 1779553958,
|
|
||||||
"result_code": 1
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"user_deck_rotation": [],
|
|
||||||
"user_deck_unlimited": [],
|
|
||||||
"maintenance_card_list": [],
|
|
||||||
"user_deck_my_rotation": [],
|
|
||||||
"trial_deck_list": [],
|
|
||||||
"default_deck_list": {
|
|
||||||
"91": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 91,
|
|
||||||
"class_id": 1,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100111010,
|
|
||||||
100111010,
|
|
||||||
100111010,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100111020,
|
|
||||||
100111020,
|
|
||||||
100111020,
|
|
||||||
100111040,
|
|
||||||
100111040,
|
|
||||||
100111040,
|
|
||||||
100114010,
|
|
||||||
100114010,
|
|
||||||
100114010,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100111060,
|
|
||||||
100111060,
|
|
||||||
100111060,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100111030,
|
|
||||||
100111030,
|
|
||||||
100111030,
|
|
||||||
100111050,
|
|
||||||
100111050,
|
|
||||||
100111050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100111070,
|
|
||||||
100111070,
|
|
||||||
100111070,
|
|
||||||
100121010,
|
|
||||||
100121010,
|
|
||||||
100121010
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"92": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 92,
|
|
||||||
"class_id": 2,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100211010,
|
|
||||||
100211010,
|
|
||||||
100211010,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100211020,
|
|
||||||
100211020,
|
|
||||||
100211020,
|
|
||||||
100211060,
|
|
||||||
100211060,
|
|
||||||
100211060,
|
|
||||||
100214010,
|
|
||||||
100214010,
|
|
||||||
100214010,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100211030,
|
|
||||||
100211030,
|
|
||||||
100211030,
|
|
||||||
100214020,
|
|
||||||
100214020,
|
|
||||||
100214020,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100211040,
|
|
||||||
100211040,
|
|
||||||
100211040,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100211050,
|
|
||||||
100211050,
|
|
||||||
100211050,
|
|
||||||
100221020,
|
|
||||||
100221020,
|
|
||||||
100221020
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"93": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 93,
|
|
||||||
"class_id": 3,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100314010,
|
|
||||||
100314010,
|
|
||||||
100314010,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100311010,
|
|
||||||
100311010,
|
|
||||||
100311010,
|
|
||||||
100314030,
|
|
||||||
100314030,
|
|
||||||
100314030,
|
|
||||||
100314020,
|
|
||||||
100314020,
|
|
||||||
100314020,
|
|
||||||
100314040,
|
|
||||||
100314040,
|
|
||||||
100314040,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100314050,
|
|
||||||
100314050,
|
|
||||||
100314050,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100314060,
|
|
||||||
100314060,
|
|
||||||
100314060,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100314070,
|
|
||||||
100314070,
|
|
||||||
100314070,
|
|
||||||
100321010,
|
|
||||||
100321010,
|
|
||||||
100321010
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"94": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 94,
|
|
||||||
"class_id": 4,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100414020,
|
|
||||||
100414020,
|
|
||||||
100414020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100411010,
|
|
||||||
100411010,
|
|
||||||
100411010,
|
|
||||||
100414010,
|
|
||||||
100414010,
|
|
||||||
100414010,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100411050,
|
|
||||||
100411050,
|
|
||||||
100411050,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100411030,
|
|
||||||
100411030,
|
|
||||||
100411030,
|
|
||||||
100414030,
|
|
||||||
100414030,
|
|
||||||
100414030,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100411020,
|
|
||||||
100411020,
|
|
||||||
100411020,
|
|
||||||
100411040,
|
|
||||||
100411040,
|
|
||||||
100411040,
|
|
||||||
100421020,
|
|
||||||
100421020,
|
|
||||||
100421020
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"95": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 95,
|
|
||||||
"class_id": 5,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100511010,
|
|
||||||
100511010,
|
|
||||||
100511010,
|
|
||||||
100511020,
|
|
||||||
100511020,
|
|
||||||
100511020,
|
|
||||||
100514010,
|
|
||||||
100514010,
|
|
||||||
100514010,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100511030,
|
|
||||||
100511030,
|
|
||||||
100511030,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100511040,
|
|
||||||
100511040,
|
|
||||||
100511040,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100511050,
|
|
||||||
100511050,
|
|
||||||
100511050,
|
|
||||||
100514020,
|
|
||||||
100514020,
|
|
||||||
100514020,
|
|
||||||
100511060,
|
|
||||||
100511060,
|
|
||||||
100511060,
|
|
||||||
100521030,
|
|
||||||
100521030,
|
|
||||||
100521030
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"96": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 96,
|
|
||||||
"class_id": 6,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100611010,
|
|
||||||
100611010,
|
|
||||||
100611010,
|
|
||||||
100611020,
|
|
||||||
100611020,
|
|
||||||
100611020,
|
|
||||||
100614010,
|
|
||||||
100614010,
|
|
||||||
100614010,
|
|
||||||
100614020,
|
|
||||||
100614020,
|
|
||||||
100614020,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100611030,
|
|
||||||
100611030,
|
|
||||||
100611030,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100611050,
|
|
||||||
100611050,
|
|
||||||
100611050,
|
|
||||||
100614030,
|
|
||||||
100614030,
|
|
||||||
100614030,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100611040,
|
|
||||||
100611040,
|
|
||||||
100611040,
|
|
||||||
100621010,
|
|
||||||
100621010,
|
|
||||||
100621010
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"97": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 97,
|
|
||||||
"class_id": 7,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100713020,
|
|
||||||
100713020,
|
|
||||||
100713020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100713010,
|
|
||||||
100713010,
|
|
||||||
100713010,
|
|
||||||
100711010,
|
|
||||||
100711010,
|
|
||||||
100711010,
|
|
||||||
100714010,
|
|
||||||
100714010,
|
|
||||||
100714010,
|
|
||||||
100714020,
|
|
||||||
100714020,
|
|
||||||
100714020,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100713030,
|
|
||||||
100713030,
|
|
||||||
100713030,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100723010,
|
|
||||||
100723010,
|
|
||||||
100723010,
|
|
||||||
100714030,
|
|
||||||
100714030,
|
|
||||||
100714030,
|
|
||||||
100711020,
|
|
||||||
100711020,
|
|
||||||
100711020
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
},
|
|
||||||
"98": {
|
|
||||||
"null": 1,
|
|
||||||
"deck_no": 98,
|
|
||||||
"class_id": 8,
|
|
||||||
"sleeve_id": 3000011,
|
|
||||||
"leader_skin_id": 0,
|
|
||||||
"deck_name": "Default",
|
|
||||||
"card_id_array": [
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100011020,
|
|
||||||
100012010,
|
|
||||||
100811020,
|
|
||||||
100811020,
|
|
||||||
100811020,
|
|
||||||
100811060,
|
|
||||||
100811060,
|
|
||||||
100811060,
|
|
||||||
100811070,
|
|
||||||
100811070,
|
|
||||||
100811070,
|
|
||||||
100814010,
|
|
||||||
100814010,
|
|
||||||
100814010,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100011030,
|
|
||||||
100811010,
|
|
||||||
100811010,
|
|
||||||
100811010,
|
|
||||||
100811030,
|
|
||||||
100811030,
|
|
||||||
100811030,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100011040,
|
|
||||||
100811040,
|
|
||||||
100811040,
|
|
||||||
100811040,
|
|
||||||
100824010,
|
|
||||||
100824010,
|
|
||||||
100824010,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100011050,
|
|
||||||
100811050,
|
|
||||||
100811050,
|
|
||||||
100811050
|
|
||||||
],
|
|
||||||
"is_complete_deck": 1,
|
|
||||||
"is_available_deck": 1,
|
|
||||||
"maintenance_card_ids": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"user_leader_skin_setting_list": {
|
|
||||||
"1": {
|
|
||||||
"class_id": 1,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 1
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"class_id": 2,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 2
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"class_id": 3,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 3
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"class_id": 4,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 4
|
|
||||||
},
|
|
||||||
"5": {
|
|
||||||
"class_id": 5,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 5
|
|
||||||
},
|
|
||||||
"6": {
|
|
||||||
"class_id": 6,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 6
|
|
||||||
},
|
|
||||||
"7": {
|
|
||||||
"class_id": 7,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 7
|
|
||||||
},
|
|
||||||
"8": {
|
|
||||||
"class_id": 8,
|
|
||||||
"is_random_leader_skin": 0,
|
|
||||||
"leader_skin_id": 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,229 +0,0 @@
|
|||||||
{
|
|
||||||
"data_headers": {
|
|
||||||
"short_udid": 411054851,
|
|
||||||
"viewer_id": 906243102,
|
|
||||||
"sid": "",
|
|
||||||
"servertime": 1779553959,
|
|
||||||
"result_code": 1
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"user_info": {
|
|
||||||
"device_type": "2",
|
|
||||||
"name": "combusty7",
|
|
||||||
"country_code": "KOR",
|
|
||||||
"max_friend": "20",
|
|
||||||
"last_play_time": "2026-05-23 16:32:39",
|
|
||||||
"is_received_two_pick_mission": "1",
|
|
||||||
"birth": "19600101",
|
|
||||||
"selected_emblem_id": "701441011",
|
|
||||||
"selected_degree_id": "300003",
|
|
||||||
"mission_change_time": "2017-09-17 14:47:13",
|
|
||||||
"mission_receive_type": "0",
|
|
||||||
"is_official": "0",
|
|
||||||
"is_official_mark_displayed": "0"
|
|
||||||
},
|
|
||||||
"sealed_info": {
|
|
||||||
"enable": 1,
|
|
||||||
"crystal_cost": 600,
|
|
||||||
"rupy_cost": 600,
|
|
||||||
"ticket_cost": 4,
|
|
||||||
"is_join": false,
|
|
||||||
"pack_info": [
|
|
||||||
10032,
|
|
||||||
10032,
|
|
||||||
10031,
|
|
||||||
10030,
|
|
||||||
10029
|
|
||||||
],
|
|
||||||
"deck_using_num_min": 30,
|
|
||||||
"schedule_id": 21,
|
|
||||||
"is_deck_code_maintenance": false,
|
|
||||||
"sales_period_info": {
|
|
||||||
"sales_period_series": 33
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"colosseum_info": {
|
|
||||||
"colosseum_id": "165",
|
|
||||||
"is_display_tips": "0",
|
|
||||||
"tips_id": "0",
|
|
||||||
"card_pool_name": "Take Two (Dragonblade–Rivenbrandt)",
|
|
||||||
"is_colosseum_period": true,
|
|
||||||
"is_round_period": true,
|
|
||||||
"deck_format": "3",
|
|
||||||
"is_normal_two_pick": "1",
|
|
||||||
"is_special_mode": "10",
|
|
||||||
"is_all_card_enabled": 0,
|
|
||||||
"start_time": "2026-05-21 06:00:00",
|
|
||||||
"colosseum_name": "Rivenbrandt Take Two Cup",
|
|
||||||
"now_round": "1",
|
|
||||||
"end_time": "2026-05-25 19:59:59",
|
|
||||||
"sales_period_info": {
|
|
||||||
"sales_period_time": "2026-05-25 19:59:59"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is_available_colosseum_free_entry": true,
|
|
||||||
"arena_info": [
|
|
||||||
{
|
|
||||||
"mode": 1,
|
|
||||||
"enable": 1,
|
|
||||||
"cost": 150,
|
|
||||||
"rupy_cost": 150,
|
|
||||||
"ticket_cost": 1,
|
|
||||||
"is_join": false,
|
|
||||||
"format_info": {
|
|
||||||
"two_pick_type": "1",
|
|
||||||
"card_pool_name": "Take Two (Dragonblade–Rivenbrandt)",
|
|
||||||
"announce_id": 0,
|
|
||||||
"last_card_pack_set_id": "10029",
|
|
||||||
"start_time": "2026-05-01 02:00:00",
|
|
||||||
"end_time": "2026-06-01 01:59:59"
|
|
||||||
},
|
|
||||||
"sales_period_info": {
|
|
||||||
"sales_period_time": "2026-06-01 01:59:59"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"is_arena_challenge_period": true,
|
|
||||||
"is_hidden_boss_appeared": false,
|
|
||||||
"competition_info": {
|
|
||||||
"is_competition_period": false
|
|
||||||
},
|
|
||||||
"treasure_info": null,
|
|
||||||
"unread_present_count": 0,
|
|
||||||
"unreceived_mission_reward_count": 0,
|
|
||||||
"lottery_period_info": null,
|
|
||||||
"master_point_ranking_period": {
|
|
||||||
"id": "119",
|
|
||||||
"period_num": "118",
|
|
||||||
"necessary_score": "0",
|
|
||||||
"begin_time": "2026-05-01 02:00:00",
|
|
||||||
"end_time": "2026-06-01 01:59:59"
|
|
||||||
},
|
|
||||||
"last_announce_id": "3353",
|
|
||||||
"last_announce_update_time": "2026-05-15 10:22:11",
|
|
||||||
"unfinished_battle_exists": false,
|
|
||||||
"is_joined_room": false,
|
|
||||||
"receive_friend_apply_count": 0,
|
|
||||||
"feature_maintenance_list": [],
|
|
||||||
"can_give_daily_login_bonus": false,
|
|
||||||
"friend_battle_invite_count": 0,
|
|
||||||
"user_config": {
|
|
||||||
"receive_invitation": "1",
|
|
||||||
"receive_invitation_in_battle": "1",
|
|
||||||
"receive_invitation_in_offline": "1",
|
|
||||||
"receive_friend_apply": "1",
|
|
||||||
"is_allow_send_adjust": "1",
|
|
||||||
"is_foil_preferred": "0",
|
|
||||||
"is_prize_preferred": "0"
|
|
||||||
},
|
|
||||||
"banner": [
|
|
||||||
{
|
|
||||||
"image_name": "banner_000788",
|
|
||||||
"click": "account_transition_with_two",
|
|
||||||
"status": "10",
|
|
||||||
"change_time": "10",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"image_paths": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"image_name": "banner_000906",
|
|
||||||
"click": "colosseum",
|
|
||||||
"status": "",
|
|
||||||
"change_time": "10",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"image_paths": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"image_name": "banner_000220",
|
|
||||||
"click": "deck_intro_rotation",
|
|
||||||
"status": "17",
|
|
||||||
"change_time": "10",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"image_paths": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"image_name": "banner_000840",
|
|
||||||
"click": "mission",
|
|
||||||
"status": "2",
|
|
||||||
"change_time": "10",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"image_paths": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"sub_banner": null,
|
|
||||||
"sub_banner_list": [],
|
|
||||||
"user_mypage_info": {
|
|
||||||
"user_mypage_setting": {
|
|
||||||
"mypage_id": "0",
|
|
||||||
"select_type": "0",
|
|
||||||
"mypage_id_list": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"user_offline_event": [],
|
|
||||||
"convention": {
|
|
||||||
"is_join_tournament": false,
|
|
||||||
"recent_start_date": null,
|
|
||||||
"is_admin_watch_user": false
|
|
||||||
},
|
|
||||||
"special_crystal_info": [],
|
|
||||||
"room_type_in_session": {
|
|
||||||
"special_deck_format_list": [
|
|
||||||
{
|
|
||||||
"deck_format": "5",
|
|
||||||
"end_time": "2030-06-26 19:59:59"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"guild_notification": {
|
|
||||||
"guild_id": null,
|
|
||||||
"guild_room_message_id": null,
|
|
||||||
"is_join_request": false,
|
|
||||||
"is_invited": false
|
|
||||||
},
|
|
||||||
"shop_notification": {
|
|
||||||
"card_pack": {
|
|
||||||
"is_open_free_gacha_campaign": false,
|
|
||||||
"can_free_gacha": false
|
|
||||||
},
|
|
||||||
"build_deck": [],
|
|
||||||
"sleeve": [],
|
|
||||||
"leader_skin": []
|
|
||||||
},
|
|
||||||
"pre_release_status": 0,
|
|
||||||
"gathering_info": {
|
|
||||||
"has_invite": 0,
|
|
||||||
"is_entry": 0
|
|
||||||
},
|
|
||||||
"quest": {
|
|
||||||
"is_open": false,
|
|
||||||
"is_display_badge": false,
|
|
||||||
"is_daily_first_access": false,
|
|
||||||
"end_time": "",
|
|
||||||
"name": ""
|
|
||||||
},
|
|
||||||
"basic_puzzle": {
|
|
||||||
"is_display_badge": true
|
|
||||||
},
|
|
||||||
"all_card_enabled_period": null,
|
|
||||||
"user_item_list": [
|
|
||||||
{
|
|
||||||
"item_id": "1",
|
|
||||||
"number": "19"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item_id": "10011",
|
|
||||||
"number": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"item_id": "80001",
|
|
||||||
"number": "1"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"is_battle_pass_period": true,
|
|
||||||
"story_notification": {
|
|
||||||
"is_display_ribbon": false,
|
|
||||||
"is_display_badge": false
|
|
||||||
},
|
|
||||||
"home_dialog_list": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,201 +0,0 @@
|
|||||||
{
|
|
||||||
"data_headers": {
|
|
||||||
"sid": "ac631c29b5f5d07ed5fb6712ad8623c31779553960",
|
|
||||||
"short_udid": 411054851,
|
|
||||||
"viewer_id": 906243102,
|
|
||||||
"servertime": 1779553960,
|
|
||||||
"result_code": 1
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"10011": {
|
|
||||||
"record_id": "21",
|
|
||||||
"id": "8",
|
|
||||||
"store_product_id": "10011",
|
|
||||||
"name": "60-crystal set",
|
|
||||||
"text": "Purchase 60 Crystals",
|
|
||||||
"price": "0.99",
|
|
||||||
"charge_crystal_num": "60",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2022-10-05 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"30011": {
|
|
||||||
"record_id": "26",
|
|
||||||
"id": "10",
|
|
||||||
"store_product_id": "30011",
|
|
||||||
"name": "670-crystal set",
|
|
||||||
"text": "Purchase 670 Crystals",
|
|
||||||
"price": "10.99",
|
|
||||||
"charge_crystal_num": "670",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2022-10-05 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"40000": {
|
|
||||||
"record_id": "27",
|
|
||||||
"id": "4",
|
|
||||||
"store_product_id": "40000",
|
|
||||||
"name": "1200-crystal set",
|
|
||||||
"text": "Purchase 1200 Crystals",
|
|
||||||
"price": "20.99",
|
|
||||||
"charge_crystal_num": "1200",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2015-03-01 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"50000": {
|
|
||||||
"record_id": "28",
|
|
||||||
"id": "5",
|
|
||||||
"store_product_id": "50000",
|
|
||||||
"name": "2400-crystal set",
|
|
||||||
"text": "Purchase 2400 Crystals",
|
|
||||||
"price": "39.99",
|
|
||||||
"charge_crystal_num": "2400",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2015-03-01 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"60000": {
|
|
||||||
"record_id": "29",
|
|
||||||
"id": "6",
|
|
||||||
"store_product_id": "60000",
|
|
||||||
"name": "5000-crystal set",
|
|
||||||
"text": "Purchase 5000 Crystals",
|
|
||||||
"price": "79.99",
|
|
||||||
"charge_crystal_num": "5000",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2015-03-01 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"70011": {
|
|
||||||
"record_id": "24",
|
|
||||||
"id": "9",
|
|
||||||
"store_product_id": "70011",
|
|
||||||
"name": "350-crystal set",
|
|
||||||
"text": "Purchase 350 Crystals",
|
|
||||||
"price": "5.99",
|
|
||||||
"charge_crystal_num": "350",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "999999999",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal",
|
|
||||||
"start_time": "2022-10-05 15:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"80000": {
|
|
||||||
"record_id": "30",
|
|
||||||
"id": "800",
|
|
||||||
"store_product_id": "80000",
|
|
||||||
"name": "1200-crystal and Legendary set",
|
|
||||||
"text": "Purchase 1200 Crystals and Legendary set",
|
|
||||||
"price": "20.99",
|
|
||||||
"charge_crystal_num": "1200",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "3",
|
|
||||||
"special_shop_flag": "1",
|
|
||||||
"image_name": "thumbnail_crystal_strong",
|
|
||||||
"start_time": "2018-01-01 00:00:00",
|
|
||||||
"end_time": "2019-03-19 16:15:17",
|
|
||||||
"remaining_time": "604800",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"98900": {
|
|
||||||
"record_id": "19",
|
|
||||||
"id": "989",
|
|
||||||
"store_product_id": "98900",
|
|
||||||
"name": "[b]1-Time Deal![/b] 1000-crystal set",
|
|
||||||
"text": "Purchase 1000 Crystals",
|
|
||||||
"price": "15.99",
|
|
||||||
"charge_crystal_num": "1000",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "1",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal_strong",
|
|
||||||
"start_time": "2026-04-01 02:00:00",
|
|
||||||
"end_time": "2026-07-01 01:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "1",
|
|
||||||
"resale_start_date": "2026-04-01 02:00:00",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"99200": {
|
|
||||||
"record_id": "3",
|
|
||||||
"id": "992",
|
|
||||||
"store_product_id": "99200",
|
|
||||||
"name": "[b]One-time Deal![/b] 800-crystal set",
|
|
||||||
"text": "Purchase 800 Crystals",
|
|
||||||
"price": "7.99",
|
|
||||||
"charge_crystal_num": "800",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "1",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal_strong",
|
|
||||||
"start_time": "2018-01-30 04:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 0
|
|
||||||
},
|
|
||||||
"99400": {
|
|
||||||
"record_id": "10",
|
|
||||||
"id": "994",
|
|
||||||
"store_product_id": "99400",
|
|
||||||
"name": "[b]Special Offer![/b] 7500-crystal set (3 times per person)",
|
|
||||||
"text": "Purchase 7500 Crystals",
|
|
||||||
"price": "79.99",
|
|
||||||
"charge_crystal_num": "7500",
|
|
||||||
"free_crystal_num": "0",
|
|
||||||
"purchase_limit": "3",
|
|
||||||
"special_shop_flag": "0",
|
|
||||||
"image_name": "thumbnail_crystal_strong",
|
|
||||||
"start_time": "2017-06-01 06:00:00",
|
|
||||||
"end_time": "2030-03-01 14:59:59",
|
|
||||||
"remaining_time": "0",
|
|
||||||
"is_resale_product": "0",
|
|
||||||
"resale_start_date": "",
|
|
||||||
"purchase_num_current": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
0
SVSim.Bootstrap/Data/seeds/.gitkeep
Normal file
0
SVSim.Bootstrap/Data/seeds/.gitkeep
Normal file
17
SVSim.Bootstrap/Data/seeds/arena-season.json
Normal file
17
SVSim.Bootstrap/Data/seeds/arena-season.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"mode": 1,
|
||||||
|
"enable": 1,
|
||||||
|
"cost": 150,
|
||||||
|
"rupy_cost": 150,
|
||||||
|
"ticket_cost": 1,
|
||||||
|
"is_join": false,
|
||||||
|
"format_info": {
|
||||||
|
"two_pick_type": "1",
|
||||||
|
"card_pool_name": "Take Two (Dragonblade–Rivenbrandt)",
|
||||||
|
"announce_id": 0,
|
||||||
|
"last_card_pack_set_id": "10029",
|
||||||
|
"start_time": "2026-05-01 02:00:00",
|
||||||
|
"end_time": "2026-06-01 01:59:59"
|
||||||
|
}
|
||||||
|
}
|
||||||
266
SVSim.Bootstrap/Data/seeds/avatar-abilities.json
Normal file
266
SVSim.Bootstrap/Data/seeds/avatar-abilities.json
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 2801,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "-1|-7",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144051:930144061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.play_count}>=2&{me.play_count}<4)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.play_count}>=4)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144051:930144061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.play_count}>=2&{me.play_count}<4)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.play_count}>=4)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"ability_desc": "Subtract 1 from the cost of a Natura card in your hand.|Give all allied followers [b]Storm[/b] and the ability to attack 2 times per turn.",
|
||||||
|
"passive_ability_desc": "At the start of the match, if you are going second, gain 1 valor.\\nAt the end of your turn, if you've played at least 2 cards this turn, gain 1 valor. If you've played at least 4, gain 2 valor instead."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3301,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-4",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144011:930144021:930144031)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144011:930144021:930144031)(preprocess:none)",
|
||||||
|
"ability_desc": "If there are any [b]Fairies[/b] in your hand, change the cost of a random [b]Fairy[/b] in your hand to 0 until the end of the turn. Otherwise, put a [b]Fairy[/b] into your hand.|Give +1/+0 to an allied follower. Deal X damage to a random enemy follower. X equals the attack of the strongest allied follower in play.|Give +X/+Y to an allied 1-play-point follower. X and Y equal the number of allied Forestcraft followers that have left play this match, split randomly. If X plus Y is at least 20, give that follower [b]Storm[/b].<<{me.inplay.class.count}+1??\\n(Followers that have left play: <<{me.game_left_cards.unit.clan=elf.count}>>/20)>>",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4101,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "0|0|-8",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144071:930144081:930144091)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.turn_accelerate_count=me:0}>0&{me.inplay.class.turn_accelerate_count=me:0}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.turn_accelerate_count=me:0}>1)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930144071:930144081:930144091)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.turn_accelerate_count=me:0}>0&{me.inplay.class.turn_accelerate_count=me:0}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.turn_accelerate_count=me:0}>1)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"ability_desc": "Put a random follower with [b]Accelerate[/b] from your deck into your hand.|Give your leader the following effect until the end of the turn: Whenever you play a card using [b]Accelerate[/b], deal 1 damage to a random enemy follower.|Put a [b]Purgation's Blessing[/b] into your hand.\\nGive your leader the following effect: At the start of your every other turn, put a [b]Purgation's Blessing[/b] into your hand. (This effect lasts for the rest of the match.)",
|
||||||
|
"passive_ability_desc": "At the start of the match, if you are going second, gain 1 valor.\\nAt the end of your turn, if you've played a card using [b]Accelerate[/b] this turn, gain 1 valor. If you've played at least 2, gain 2 valor instead.<<{me.inplay.class.count}+1??\\n(Times [b]Accelerate[/b][b]d[/b]: <<{me.inplay.class.turn_accelerate_count_text=me:0}>>)>>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2602,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-2|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244041:930244051:930244061)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244041:930244051:930244061)(preprocess:none)",
|
||||||
|
"ability_desc": "Give +1/+0 to a random allied follower.\\nAt the start of your next turn, draw a card.|Summon an [b]Arcane Personnel Carrier[/b].\\n[b]Rally[/b] [b](10)[/b]: Summon a [b]Val, Speedy Magicar[/b].<<{me.inplay.class.count}+1??\\n([b]Rally[/b] count: <<{me.inplay.class.rally_count}>>/10)>>|Deal 3 damage to a random enemy. Do this 2 times.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3302,
|
||||||
|
"battle_start_first_player_turn_bp": 4,
|
||||||
|
"battle_start_second_player_turn_bp": 4,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-6",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244071:930244081:930244091)(preprocess:none),(skill:change_affiliation)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:{me.hand.unit})(option:tribe=legion&type=add)(preprocess:none),(skill:change_affiliation)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:{me.deck.unit})(option:tribe=legion&type=add)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244071:930244081:930244091)(preprocess:none),(skill:change_affiliation)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:{me.hand.unit})(option:tribe=legion&type=add)(preprocess:none),(skill:change_affiliation)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:{me.deck.unit})(option:tribe=legion&type=add)(preprocess:none)",
|
||||||
|
"ability_desc": "Discard a follower from your hand and put a copy of it into your deck. Give that copy the Officer trait.\\nDraw a card.|At the end of your turn, deal 2 damage to a random enemy follower. Before damage is dealt, if there are fewer allied followers than enemy followers in play, gain 1 valor.|Give your leader the following effect: Once on each of your turns, when you play a follower, put a random X-play-point follower from your deck into play. X equals the original cost of the follower you played. (This effect lasts for the rest of the match.)",
|
||||||
|
"passive_ability_desc": "At the start of your turn, if this is your first turn, give the Officer trait to all followers in your hand and deck."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3502,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-2|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244011:930244021:930244031)(preprocess:none),(skill:change_rally_count)(timing:when_play_other)(condition:{me.inplay_self.count}>0&character=me&target=played_card&card_type=spell&base_card_id=900214050)(target:character=me&target=inplay&card_type=class)(option:add_rally_count=1)(preprocess:per_turn=1),(skill:pp_modifier)(timing:when_play_other)(condition:{me.inplay_self.count}>0&character=me&target=played_card&card_type=spell&base_card_id=900214050)(target:character=me&target=inplay&card_type=class)(option:add_pp=1)(preprocess:per_turn=1)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930244011:930244021:930244031)(preprocess:none),(skill:change_rally_count)(timing:when_play_other)(condition:{me.inplay_self.count}>0&character=me&target=played_card&card_type=spell&base_card_id=900214050)(target:character=me&target=inplay&card_type=class)(option:add_rally_count=1)(preprocess:per_turn=1),(skill:pp_modifier)(timing:when_play_other)(condition:{me.inplay_self.count}>0&character=me&target=played_card&card_type=spell&base_card_id=900214050)(target:character=me&target=inplay&card_type=class)(option:add_pp=1)(preprocess:per_turn=1)",
|
||||||
|
"ability_desc": "Discard a card from your hand.\\nPut a random Festive card from your deck into your hand.|Give your leader the following effect: The next time your leader takes damage, reduce that damage to 0.|Give your leader the following effect until the end of the turn: Whenever you play a [b]Glittering Gold[/b], give +1/+0 to all allied followers and draw a card.",
|
||||||
|
"passive_ability_desc": "Once on each of your turns, when you play a [b]Glittering Gold[/b], add 1 to your [b]Rally[/b] count and recover 1 play point."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3903,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344071:930344081:930344091)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344071:930344081:930344091)(preprocess:none)",
|
||||||
|
"ability_desc": "Select a card in your hand. If it's been [b]Spellboost[/b][b]ed[/b] less than 5 times, [b]Spellboost[/b] it. Otherwise, put a copy of that card into your deck and subtract 1 from the copy's cost.|Discard a card with [b]Spellboost[/b] from your hand. Put a random card with [b]Spellboost[/b] from your deck into your hand and [b]Spellboost[/b] it X times. X equals the number of times the discarded card had been [b]Spellboost[/b][b]ed[/b].|Select a card with [b]Spellboost[/b] in your hand. Put a copy of it into your hand and [b]Spellboost[/b] the copy X times. X equals the number of times the selected card has been [b]Spellboost[/b][b]ed[/b].",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2523,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "0|-1|-8",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344011:930344021:930344031)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards.all.play_moment_tribe=machine.count}>0&{me.turn_play_cards.all.play_moment_tribe=machine.count}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards.all.play_moment_tribe=machine.count}>=2)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344011:930344021:930344031)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards.all.play_moment_tribe=machine.count}>0&{me.turn_play_cards.all.play_moment_tribe=machine.count}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards.all.play_moment_tribe=machine.count}>=2)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"ability_desc": "Put a [b]Recovery[/b] into your hand.|Until the end of the turn, subtract 1 from the cost of a Machina card in your hand.|Discard 2 cards from your hand.\\nPut a [b]Ladica, Verdant Claw[/b] and [b]Azure Blast[/b] into your hand.",
|
||||||
|
"passive_ability_desc": "At the start of the match, if you are going second, gain 1 valor.\\nAt the end of your turn, if you've played at least 1 Machina card this turn, gain 1 valor. If you've played at least 2, gain 2 valor instead.<<{me.inplay.class.count}+1??\\n(Machina cards played: <<{me.turn_play_cards_other_self.all.play_moment_tribe=machine.count}>>)>>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4103,
|
||||||
|
"battle_start_first_player_turn_bp": 2,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344041:930344051:930344061)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930344041:930344051:930344061)(preprocess:none)",
|
||||||
|
"ability_desc": "Put 1 of the following cards into your hand in order and change its cost to 0.\\n<<${me.inplay.class.count}>0&{me.game_skill_activated.base_card_id=930344040.count}%2=0?[9acd32]1.[-]?1.>> [b]Insight[/b]\\n<<${me.inplay.class.count}>0&{me.game_skill_activated.base_card_id=930344040.count}%2=1?[9acd32]2.[-]?2.>> [b]Angelic Snipe[/b]|Give an unevolved allied follower the following effect and evolve it: At the end of your turn, banish this follower. ([b]Evolve[/b] effects will not activate.)|Change the cost, attack, and defense of a follower in your hand to 1.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2804,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "-1|-1|-6",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444041:930444051:930444061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.destroyed_this_turn_card_list.all.base_card_id=900012050.count}>0)(target:character=me&target=inplay&card_type=class)(option:add_bp={me.destroyed_this_turn_card_list.all.base_card_id=900012050.count})(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444041:930444051:930444061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.destroyed_this_turn_card_list.all.base_card_id=900012050.count}>0)(target:character=me&target=inplay&card_type=class)(option:add_bp={me.destroyed_this_turn_card_list.all.base_card_id=900012050.count})(preprocess:none)",
|
||||||
|
"ability_desc": "Give an allied Natura follower +1/+0 and [b]Rush[/b].|Subtract 1 from the cost of a Natura card in your hand until the end of the turn.|Give your leader the following effect: Once on each of your turns, when an allied [b]Naterran World Tree[/b] is destroyed, if it's the second this turn, summon a [b]Bayleon, Shining Sovereign[/b] and activate its [b]Fanfare[/b] effect. (This effect lasts for the rest of the match.) If your leader already has this effect, give +1/+1 to all allied followers and restore 3 defense to your leader instead.<<{me.inplay.class.count}+1??\\n([b]Naterran World Tree[/b][b]s[/b] destroyed: <<{me.destroyed_this_turn_card_list.all.base_card_id=900012050.count}>>/2)>>",
|
||||||
|
"passive_ability_desc": "At the start of the match, if you are going second, gain 1 valor.\\nAt the end of your turn, gain X valor. X equals the number of allied [b]Naterran World Tree[/b][b]s[/b] destroyed this turn.<<{me.inplay.class.count}+1??\\n([b]Naterran World Tree[/b][b]s[/b] destroyed: <<{me.destroyed_this_turn_card_list.all.base_card_id=900012050.count}>>)>>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2604,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-5",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444011:930444021:930444031)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444011:930444021:930444031)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to a follower or the enemy leader. If you selected an allied follower, give +0/+2 to that follower.|Select a follower in play. Give it +2/+0 and deal 2 damage to it. If that follower is not destroyed by this effect, gain 1 valor.|Give your leader the following effect: Once on each of your turns after you become able to evolve, when an allied follower takes damage, if it's not destroyed, give it +2/+2 and deal 5 damage to a random enemy follower. (This effect lasts for the rest of the match.)",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3504,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-6",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444071:930444081:930444091)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930444071:930444081:930444091)(preprocess:none)",
|
||||||
|
"ability_desc": "At the end of your turn, draw a card.|Discard a card from your hand.\\nDeal 2 damage to a random enemy follower and 1 damage to the enemy leader.|Put a [b]Tidal Surge[/b] into your hand.\\nGive your leader the following effect: At the start of your turn, if there are no [b]Tidal Surge[/b][b]s[/b] in your hand, put 1 into your hand. (This effect lasts for the rest of the match.)",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1605,
|
||||||
|
"battle_start_first_player_turn_bp": 2,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-4",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544041:930544051:930544061)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544041:930544051:930544061)(preprocess:none)",
|
||||||
|
"ability_desc": "If there are any [b]Assembly Droid[/b][b]s[/b] in your hand, change the cost of a random [b]Assembly Droid[/b] in your hand to 0 until the end of the turn. Otherwise, put an [b]Assembly Droid[/b] into your hand.|Summon a [b]Roly-Poly Mk I, Stalwart Bot[/b] and evolve it.|Discard 2 cards from your hand.\\nPut a [b]Tetra, Sapphire Leader[/b] and [b]Mono, Garnet Challenger[/b] into your hand.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2605,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-2|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544071:930544081:930544091)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544071:930544081:930544091)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to a follower or the enemy leader. If you selected an allied follower, before damage is dealt, give it [b]Last Words[/b]: Draw a card.|Activate an allied follower's [b]Last Words[/b] effects.|Give an allied follower the following effects.\\n-[b]Rush[/b].\\n-[b]Strike[/b]: Gain +2/+0.\\n-[b]Follower[/b] [b]Strike[/b]: Deal X damage to the enemy leader. X equals this follower's attack.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3505,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544011:930544021:930544031)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930544011:930544021:930544031)(preprocess:none)",
|
||||||
|
"ability_desc": "Give a random allied follower the following effect: When this follower leaves play, draw a card.|Until the end of the turn, subtract 2 from the cost of a follower in your hand and give it the following effect: If this follower is in play, when it leaves play, or at the end of your turn, banish this follower.|Give an allied follower [b]Rush[/b], [b]Bane[/b], and [b]Last Words[/b]: [b]Necromancy[/b] [b](2)[/b] - Summon a copy of this follower and give it [b]Storm[/b]. If you have at least 10 shadows, perform [b]Necromancy[/b] [b](10)[/b] - Summon 2 copies instead and give them [b]Storm[/b].",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1606,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-2|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644041:930644051:930644061)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644041:930644051:930644061)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to a random enemy. If [b]Vengeance[/b] is active for you, deal 2 damage instead, and at the start of your next turn, draw a card.|Activate [b]Vengeance[/b] until the end of your next turn, even if your leader's defense is greater than 10.|Give your leader the following effect until the end of the turn: Whenever an unevolved allied follower's attack or defense is increased by an effect, evolve that follower and give it [b]Storm[/b].",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2606,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-2",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644011:930644021:930644031)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644011:930644021:930644031)(preprocess:none)",
|
||||||
|
"ability_desc": "Give +1/+0 to a random allied [b]Forest Bat[/b].\\nDraw a card.|Evolve an allied [b]Forest Bat[/b] and give it [b]Last Words[/b]: Give your leader the following effect - At the end of your opponent's turn, summon a [b]Forest Bat[/b], then remove this effect.|Summon 2 [b]Forest Bat[/b][b]s[/b].\\nDeal X damage to the enemy leader. X equals the number of allied [b]Forest Bat[/b][b]s[/b] in play.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3506,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 1,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644071:930644081:930644091)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930644071:930644081:930644091)(preprocess:none)",
|
||||||
|
"ability_desc": "Give a follower in you hand [b]Fanfare[/b]: Randomly activate 1 of the following effects.\\n-Deal 1 damage to the enemy leader.\\n-Restore 1 defense to your leader.|At the start of your next turn, draw a card.\\nIf it's a turn you are able to evolve, you have at least 1 valor, and you have 0 evolution points, use 1 valor and recover 1 evolution point.|Give your leader the following effect until the end of the turn: Whenever an allied follower evolves, recover 1 play point and deal 1 damage to the enemy leader.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2507,
|
||||||
|
"battle_start_first_player_turn_bp": 1,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "-1|-5",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744051:930744061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}>0&{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}>=2)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744051:930744061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}>0&{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}<2)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}>=2)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none)",
|
||||||
|
"ability_desc": "Put copies of 2 different allied Natura cards fused this match into your hand.|Give your leader the following effect: At the end of your turn, deal X damage to a random enemy follower. If no enemy followers are in play, deal X damage to the enemy leader. X equals half the number of allied Natura cards fused this match (rounded up). (This effect lasts for the rest of the match.)<<{me.inplay.class.count}+1??\\n(X equals: <<{me.game_fusion_ingrediented_cards.all.tribe=nature.count.half_round_up}>>)>>",
|
||||||
|
"passive_ability_desc": "At the start of the match, if you are going second, gain 1 valor.\\nAt the end of your turn, if you've fused or played a Natura card this turn, gain 1 valor. If you've fused or played at least 2, gain 2 valor instead.<<${me.inplay.class.is_turn=self}=1&{me.inplay.class.count}>0?\\n(Natura cards fused or played: <<{me.turn_play_cards_other_self.all.play_moment_tribe=nature.count}+{me.fusion_ingrediented_this_turn_card_list.all.tribe=nature.count}>>)?>><<${me.inplay.class.is_turn=self}=0&{me.inplay.class.count}>0?\\n(Natura cards fused or played: 0)?>>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2607,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-6",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744071:930744081:930744091)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744071:930744081:930744091)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to an enemy.|Subtract 1 from the [b]Countdown[/b] of an allied amulet. Then, if that amulet's [b]Countdown[/b] reached 0, gain 1 valor.|Subtract 2 from the [b]Countdown[/b] of all allied amulets and gain X valor. X equals the number of amulets destroyed by this effect. If X is at least 4, put a [b]Fiery Reproach[/b] into your hand.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4107,
|
||||||
|
"battle_start_first_player_turn_bp": 0,
|
||||||
|
"battle_start_second_player_turn_bp": 0,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "0|0|-9",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744011:930744021:930744031)(preprocess:none),(skill:bp_modifier)(timing:when_evolve_other)(condition:{me.evolution_card.unit.count}>0&turn=self)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930744011:930744021:930744031)(preprocess:none),(skill:bp_modifier)(timing:when_evolve_other)(condition:{me.evolution_card.unit.count}>0&turn=self)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none)",
|
||||||
|
"ability_desc": "Give +0/+1 to an allied follower. If it's an evolved follower, give it +0/+2 instead.|Discard a card from your hand and put a copy of it into your deck.\\nDraw a card.|Recover all of your evolution points. \\nDraw cards until there are 7 cards in your hand and subtract 3 from the costs of all cards in your hand.",
|
||||||
|
"passive_ability_desc": "During your turn, whenever an allied follower evolves, gain 1 valor."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 508,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-1|-5",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844071:930844081:930844091)(preprocess:none),(skill:summon_token)(timing:self_turn_start)(condition:{me.inplay.field.base_card_id=122033010.count}=0&{me.hand.field.base_card_id=122033010.count}=0)(target:none)(option:summon_token=122033011)(preprocess:none),(skill:chant_count_change)(timing:self_turn_start)(condition:{me.inplay.field.base_card_id=122033010.count}=0&{me.hand.field.base_card_id=122033010.count}=0)(target:character=me&target=skill_summoned_card&card_type=chant_field)(option:add_chant=10)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844071:930844081:930844091)(preprocess:none),(skill:summon_token)(timing:self_turn_start)(condition:{me.inplay.field.base_card_id=122033010.count}=0&{me.hand.field.base_card_id=122033010.count}=0)(target:none)(option:summon_token=122033011)(preprocess:none),(skill:chant_count_change)(timing:self_turn_start)(condition:{me.inplay.field.base_card_id=122033010.count}=0&{me.hand.field.base_card_id=122033010.count}=0)(target:character=me&target=skill_summoned_card&card_type=chant_field)(option:add_chant=10)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to a follower or the enemy leader. If you selected an allied [b]Shadow Soldier[/b], before damage is dealt, give it +1/+1.|Destroy an allied follower that cost 5 or less play points. Give a random allied follower +X/+X. X equals the cost of the destroyed follower.|Give your leader the following effect: Whenever an allied [b]Shadow Soldier[/b], [b]Shadow Commander[/b], [b]Shadow Berserker[/b], or [b]Shadow General[/b] comes into play, give it [b]Storm[/b]. (This effect lasts for the rest of the match.)",
|
||||||
|
"passive_ability_desc": "At the start of your turn, if there aren't any allied [b]Brand of the Morning Star[/b][b]s[/b] in your hand or in play, summon 1 and add 10 to its [b]Countdown[/b]."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3908,
|
||||||
|
"battle_start_first_player_turn_bp": 2,
|
||||||
|
"battle_start_second_player_turn_bp": 2,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|0|-X",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844041:930844051:930844061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=1&{me.inplay.class.pp}<3)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=3)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none),(skill:draw)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=3)(target:character=me&target=deck&card_type=all&random_count=1)(option:none)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844041:930844051:930844061)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=1&{me.inplay.class.pp}<3)(target:character=me&target=inplay&card_type=class)(option:add_bp=1)(preprocess:none),(skill:bp_modifier)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=3)(target:character=me&target=inplay&card_type=class)(option:add_bp=2)(preprocess:none),(skill:draw)(timing:self_turn_end)(condition:{me.inplay.class.pp}>=3)(target:character=me&target=deck&card_type=all&random_count=1)(option:none)(preprocess:none)",
|
||||||
|
"ability_desc": "Deal 1 damage to an enemy.|Recover 1 play point.|Give +X/+0 to an allied follower. If X is at least 10, give it [b]Storm[/b]. X equals the amount of valor you have.<<{me.inplay.class.count}+1??\\n(X equals: <<{me.inplay.class.bp}>>/10)>>",
|
||||||
|
"passive_ability_desc": "At the end of your turn, if you have at least 1 play point, gain 1 valor. If you have at least 3 play points, gain 2 valor and draw a card instead."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2518,
|
||||||
|
"battle_start_first_player_turn_bp": 3,
|
||||||
|
"battle_start_second_player_turn_bp": 3,
|
||||||
|
"battle_start_max_life": 25,
|
||||||
|
"ability_cost": "+1|-2|-3",
|
||||||
|
"ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844011:930844021:930844031)(preprocess:none)",
|
||||||
|
"passive_ability": "(skill:choice)(timing:when_choice_brave)(condition:character=me)(target:none)(option:card_id=930844011:930844021:930844031)(preprocess:none)",
|
||||||
|
"ability_desc": "If [b]Resonance[/b] is active for you, subtract 1 from the cost of a random [b]Paradigm Shift[/b] in your hand. Otherwise, deal 1 damage to a random enemy follower and then the enemy leader.|Summon an [b]Acceleratium[/b].|Give your leader the following effect until the end of the turn: Whenever an allied Artifact card comes into play, recover 1 play point and draw a card.",
|
||||||
|
"passive_ability_desc": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
38
SVSim.Bootstrap/Data/seeds/banners.json
Normal file
38
SVSim.Bootstrap/Data/seeds/banners.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"image_name": "banner_000788",
|
||||||
|
"click": "account_transition_with_two",
|
||||||
|
"status": "10",
|
||||||
|
"change_time": 10,
|
||||||
|
"remaining_time": 0,
|
||||||
|
"image_paths": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"image_name": "banner_000906",
|
||||||
|
"click": "colosseum",
|
||||||
|
"status": "",
|
||||||
|
"change_time": 10,
|
||||||
|
"remaining_time": 0,
|
||||||
|
"image_paths": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"image_name": "banner_000220",
|
||||||
|
"click": "deck_intro_rotation",
|
||||||
|
"status": "17",
|
||||||
|
"change_time": 10,
|
||||||
|
"remaining_time": 0,
|
||||||
|
"image_paths": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"image_name": "banner_000840",
|
||||||
|
"click": "mission",
|
||||||
|
"status": "2",
|
||||||
|
"change_time": 10,
|
||||||
|
"remaining_time": 0,
|
||||||
|
"image_paths": []
|
||||||
|
}
|
||||||
|
]
|
||||||
402
SVSim.Bootstrap/Data/seeds/battle-pass-levels.json
Normal file
402
SVSim.Bootstrap/Data/seeds/battle-pass-levels.json
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"level": 1,
|
||||||
|
"required_point": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 2,
|
||||||
|
"required_point": 500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 3,
|
||||||
|
"required_point": 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 4,
|
||||||
|
"required_point": 1500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 5,
|
||||||
|
"required_point": 2000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 6,
|
||||||
|
"required_point": 2500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 7,
|
||||||
|
"required_point": 3000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 8,
|
||||||
|
"required_point": 3500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 9,
|
||||||
|
"required_point": 4000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 10,
|
||||||
|
"required_point": 4500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 11,
|
||||||
|
"required_point": 5000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 12,
|
||||||
|
"required_point": 5500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 13,
|
||||||
|
"required_point": 6000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 14,
|
||||||
|
"required_point": 6500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 15,
|
||||||
|
"required_point": 7000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 16,
|
||||||
|
"required_point": 7500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 17,
|
||||||
|
"required_point": 8000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 18,
|
||||||
|
"required_point": 8500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 19,
|
||||||
|
"required_point": 9000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 20,
|
||||||
|
"required_point": 9500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 21,
|
||||||
|
"required_point": 10000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 22,
|
||||||
|
"required_point": 10500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 23,
|
||||||
|
"required_point": 11000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 24,
|
||||||
|
"required_point": 11500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 25,
|
||||||
|
"required_point": 12000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 26,
|
||||||
|
"required_point": 12500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 27,
|
||||||
|
"required_point": 13000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 28,
|
||||||
|
"required_point": 13500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 29,
|
||||||
|
"required_point": 14000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 30,
|
||||||
|
"required_point": 14500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 31,
|
||||||
|
"required_point": 15000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 32,
|
||||||
|
"required_point": 15500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 33,
|
||||||
|
"required_point": 16000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 34,
|
||||||
|
"required_point": 16500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 35,
|
||||||
|
"required_point": 17000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 36,
|
||||||
|
"required_point": 17500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 37,
|
||||||
|
"required_point": 18000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 38,
|
||||||
|
"required_point": 18500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 39,
|
||||||
|
"required_point": 19000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 40,
|
||||||
|
"required_point": 19500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 41,
|
||||||
|
"required_point": 20000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 42,
|
||||||
|
"required_point": 20500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 43,
|
||||||
|
"required_point": 21000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 44,
|
||||||
|
"required_point": 21500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 45,
|
||||||
|
"required_point": 22000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 46,
|
||||||
|
"required_point": 22500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 47,
|
||||||
|
"required_point": 23000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 48,
|
||||||
|
"required_point": 23500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 49,
|
||||||
|
"required_point": 24000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 50,
|
||||||
|
"required_point": 24500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 51,
|
||||||
|
"required_point": 25000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 52,
|
||||||
|
"required_point": 25500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 53,
|
||||||
|
"required_point": 26000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 54,
|
||||||
|
"required_point": 26500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 55,
|
||||||
|
"required_point": 27000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 56,
|
||||||
|
"required_point": 27500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 57,
|
||||||
|
"required_point": 28000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 58,
|
||||||
|
"required_point": 28500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 59,
|
||||||
|
"required_point": 29000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 60,
|
||||||
|
"required_point": 29500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 61,
|
||||||
|
"required_point": 30000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 62,
|
||||||
|
"required_point": 30500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 63,
|
||||||
|
"required_point": 31000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 64,
|
||||||
|
"required_point": 31500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 65,
|
||||||
|
"required_point": 32000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 66,
|
||||||
|
"required_point": 32500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 67,
|
||||||
|
"required_point": 33000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 68,
|
||||||
|
"required_point": 33500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 69,
|
||||||
|
"required_point": 34000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 70,
|
||||||
|
"required_point": 34500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 71,
|
||||||
|
"required_point": 35000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 72,
|
||||||
|
"required_point": 35500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 73,
|
||||||
|
"required_point": 36000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 74,
|
||||||
|
"required_point": 36500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 75,
|
||||||
|
"required_point": 37000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 76,
|
||||||
|
"required_point": 37500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 77,
|
||||||
|
"required_point": 38000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 78,
|
||||||
|
"required_point": 38500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 79,
|
||||||
|
"required_point": 39000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 80,
|
||||||
|
"required_point": 39500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 81,
|
||||||
|
"required_point": 40000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 82,
|
||||||
|
"required_point": 40500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 83,
|
||||||
|
"required_point": 41000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 84,
|
||||||
|
"required_point": 41500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 85,
|
||||||
|
"required_point": 42000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 86,
|
||||||
|
"required_point": 42500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 87,
|
||||||
|
"required_point": 43000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 88,
|
||||||
|
"required_point": 43500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 89,
|
||||||
|
"required_point": 44000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 90,
|
||||||
|
"required_point": 44500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 91,
|
||||||
|
"required_point": 45000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 92,
|
||||||
|
"required_point": 45500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 93,
|
||||||
|
"required_point": 46000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 94,
|
||||||
|
"required_point": 46500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 95,
|
||||||
|
"required_point": 47000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 96,
|
||||||
|
"required_point": 47500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 97,
|
||||||
|
"required_point": 48000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 98,
|
||||||
|
"required_point": 48500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 99,
|
||||||
|
"required_point": 49000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 100,
|
||||||
|
"required_point": 49500
|
||||||
|
}
|
||||||
|
]
|
||||||
1289
SVSim.Bootstrap/Data/seeds/battle-pass-rewards.json
Normal file
1289
SVSim.Bootstrap/Data/seeds/battle-pass-rewards.json
Normal file
File diff suppressed because it is too large
Load Diff
12
SVSim.Bootstrap/Data/seeds/battle-pass-seasons.json
Normal file
12
SVSim.Bootstrap/Data/seeds/battle-pass-seasons.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"name": "Season 23",
|
||||||
|
"max_level": 100,
|
||||||
|
"start_date": "2026-04-01T02:00:00+09:00",
|
||||||
|
"end_date": "2026-07-01T01:59:59+09:00",
|
||||||
|
"can_purchase": true,
|
||||||
|
"price_crystal": 980,
|
||||||
|
"description": "Unlock the Premium track and earn exclusive rewards through {0}."
|
||||||
|
}
|
||||||
|
]
|
||||||
1648
SVSim.Bootstrap/Data/seeds/build-deck-catalog.json
Normal file
1648
SVSim.Bootstrap/Data/seeds/build-deck-catalog.json
Normal file
File diff suppressed because it is too large
Load Diff
4
SVSim.Bootstrap/Data/seeds/challenge-config.json
Normal file
4
SVSim.Bootstrap/Data/seeds/challenge-config.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"use_two_pick_premium_card": false,
|
||||||
|
"two_pick_sleeve_id": 3000011
|
||||||
|
}
|
||||||
20
SVSim.Bootstrap/Data/seeds/colosseum.json
Normal file
20
SVSim.Bootstrap/Data/seeds/colosseum.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"colosseum_id": "165",
|
||||||
|
"colosseum_name": "Rivenbrandt Take Two Cup",
|
||||||
|
"card_pool_name": "Take Two (Dragonblade–Rivenbrandt)",
|
||||||
|
"deck_format": "3",
|
||||||
|
"start_time": "2026-05-21 06:00:00",
|
||||||
|
"end_time": "2026-05-25 19:59:59",
|
||||||
|
"now_round": "1",
|
||||||
|
"is_display_tips": "0",
|
||||||
|
"tips_id": "0",
|
||||||
|
"is_colosseum_period": true,
|
||||||
|
"is_round_period": true,
|
||||||
|
"is_normal_two_pick": "1",
|
||||||
|
"is_special_mode": "10",
|
||||||
|
"is_all_card_enabled": 0,
|
||||||
|
"sales_period_info": {
|
||||||
|
"sales_period_time": "2026-05-25 19:59:59"
|
||||||
|
}
|
||||||
|
}
|
||||||
14
SVSim.Bootstrap/Data/seeds/daily-login-bonus.json
Normal file
14
SVSim.Bootstrap/Data/seeds/daily-login-bonus.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"bonus_data": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"bonus_data": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"bonus_data": []
|
||||||
|
}
|
||||||
|
]
|
||||||
394
SVSim.Bootstrap/Data/seeds/default-decks.json
Normal file
394
SVSim.Bootstrap/Data/seeds/default-decks.json
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 91,
|
||||||
|
"class_id": 1,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100111010,
|
||||||
|
100111010,
|
||||||
|
100111010,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100111020,
|
||||||
|
100111020,
|
||||||
|
100111020,
|
||||||
|
100111040,
|
||||||
|
100111040,
|
||||||
|
100111040,
|
||||||
|
100114010,
|
||||||
|
100114010,
|
||||||
|
100114010,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100111060,
|
||||||
|
100111060,
|
||||||
|
100111060,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100111030,
|
||||||
|
100111030,
|
||||||
|
100111030,
|
||||||
|
100111050,
|
||||||
|
100111050,
|
||||||
|
100111050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100111070,
|
||||||
|
100111070,
|
||||||
|
100111070,
|
||||||
|
100121010,
|
||||||
|
100121010,
|
||||||
|
100121010
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 92,
|
||||||
|
"class_id": 2,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100211010,
|
||||||
|
100211010,
|
||||||
|
100211010,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100211020,
|
||||||
|
100211020,
|
||||||
|
100211020,
|
||||||
|
100211060,
|
||||||
|
100211060,
|
||||||
|
100211060,
|
||||||
|
100214010,
|
||||||
|
100214010,
|
||||||
|
100214010,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100211030,
|
||||||
|
100211030,
|
||||||
|
100211030,
|
||||||
|
100214020,
|
||||||
|
100214020,
|
||||||
|
100214020,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100211040,
|
||||||
|
100211040,
|
||||||
|
100211040,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100211050,
|
||||||
|
100211050,
|
||||||
|
100211050,
|
||||||
|
100221020,
|
||||||
|
100221020,
|
||||||
|
100221020
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 93,
|
||||||
|
"class_id": 3,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100314010,
|
||||||
|
100314010,
|
||||||
|
100314010,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100311010,
|
||||||
|
100311010,
|
||||||
|
100311010,
|
||||||
|
100314030,
|
||||||
|
100314030,
|
||||||
|
100314030,
|
||||||
|
100314020,
|
||||||
|
100314020,
|
||||||
|
100314020,
|
||||||
|
100314040,
|
||||||
|
100314040,
|
||||||
|
100314040,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100314050,
|
||||||
|
100314050,
|
||||||
|
100314050,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100314060,
|
||||||
|
100314060,
|
||||||
|
100314060,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100314070,
|
||||||
|
100314070,
|
||||||
|
100314070,
|
||||||
|
100321010,
|
||||||
|
100321010,
|
||||||
|
100321010
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 94,
|
||||||
|
"class_id": 4,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100414020,
|
||||||
|
100414020,
|
||||||
|
100414020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100411010,
|
||||||
|
100411010,
|
||||||
|
100411010,
|
||||||
|
100414010,
|
||||||
|
100414010,
|
||||||
|
100414010,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100411050,
|
||||||
|
100411050,
|
||||||
|
100411050,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100411030,
|
||||||
|
100411030,
|
||||||
|
100411030,
|
||||||
|
100414030,
|
||||||
|
100414030,
|
||||||
|
100414030,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100411020,
|
||||||
|
100411020,
|
||||||
|
100411020,
|
||||||
|
100411040,
|
||||||
|
100411040,
|
||||||
|
100411040,
|
||||||
|
100421020,
|
||||||
|
100421020,
|
||||||
|
100421020
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 95,
|
||||||
|
"class_id": 5,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100511010,
|
||||||
|
100511010,
|
||||||
|
100511010,
|
||||||
|
100511020,
|
||||||
|
100511020,
|
||||||
|
100511020,
|
||||||
|
100514010,
|
||||||
|
100514010,
|
||||||
|
100514010,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100511030,
|
||||||
|
100511030,
|
||||||
|
100511030,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100511040,
|
||||||
|
100511040,
|
||||||
|
100511040,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100511050,
|
||||||
|
100511050,
|
||||||
|
100511050,
|
||||||
|
100514020,
|
||||||
|
100514020,
|
||||||
|
100514020,
|
||||||
|
100511060,
|
||||||
|
100511060,
|
||||||
|
100511060,
|
||||||
|
100521030,
|
||||||
|
100521030,
|
||||||
|
100521030
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 96,
|
||||||
|
"class_id": 6,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100611010,
|
||||||
|
100611010,
|
||||||
|
100611010,
|
||||||
|
100611020,
|
||||||
|
100611020,
|
||||||
|
100611020,
|
||||||
|
100614010,
|
||||||
|
100614010,
|
||||||
|
100614010,
|
||||||
|
100614020,
|
||||||
|
100614020,
|
||||||
|
100614020,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100611030,
|
||||||
|
100611030,
|
||||||
|
100611030,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100611050,
|
||||||
|
100611050,
|
||||||
|
100611050,
|
||||||
|
100614030,
|
||||||
|
100614030,
|
||||||
|
100614030,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100611040,
|
||||||
|
100611040,
|
||||||
|
100611040,
|
||||||
|
100621010,
|
||||||
|
100621010,
|
||||||
|
100621010
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 97,
|
||||||
|
"class_id": 7,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100713020,
|
||||||
|
100713020,
|
||||||
|
100713020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100713010,
|
||||||
|
100713010,
|
||||||
|
100713010,
|
||||||
|
100711010,
|
||||||
|
100711010,
|
||||||
|
100711010,
|
||||||
|
100714010,
|
||||||
|
100714010,
|
||||||
|
100714010,
|
||||||
|
100714020,
|
||||||
|
100714020,
|
||||||
|
100714020,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100713030,
|
||||||
|
100713030,
|
||||||
|
100713030,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100723010,
|
||||||
|
100723010,
|
||||||
|
100723010,
|
||||||
|
100714030,
|
||||||
|
100714030,
|
||||||
|
100714030,
|
||||||
|
100711020,
|
||||||
|
100711020,
|
||||||
|
100711020
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 98,
|
||||||
|
"class_id": 8,
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"leader_skin_id": 0,
|
||||||
|
"deck_name": "Default",
|
||||||
|
"card_id_array": [
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100011020,
|
||||||
|
100012010,
|
||||||
|
100811020,
|
||||||
|
100811020,
|
||||||
|
100811020,
|
||||||
|
100811060,
|
||||||
|
100811060,
|
||||||
|
100811060,
|
||||||
|
100811070,
|
||||||
|
100811070,
|
||||||
|
100811070,
|
||||||
|
100814010,
|
||||||
|
100814010,
|
||||||
|
100814010,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100011030,
|
||||||
|
100811010,
|
||||||
|
100811010,
|
||||||
|
100811010,
|
||||||
|
100811030,
|
||||||
|
100811030,
|
||||||
|
100811030,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100011040,
|
||||||
|
100811040,
|
||||||
|
100811040,
|
||||||
|
100811040,
|
||||||
|
100824010,
|
||||||
|
100824010,
|
||||||
|
100824010,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100011050,
|
||||||
|
100811050,
|
||||||
|
100811050,
|
||||||
|
100811050
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
1
SVSim.Bootstrap/Data/seeds/feature-maintenances.json
Normal file
1
SVSim.Bootstrap/Data/seeds/feature-maintenances.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
530
SVSim.Bootstrap/Data/seeds/loading-exclusion-cards.json
Normal file
530
SVSim.Bootstrap/Data/seeds/loading-exclusion-cards.json
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"card_id": 100011020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101011030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101021020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101031040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101111010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101111020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101111050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100111050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101121080
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101141010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101311060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101311070
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101321030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101321050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101211010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100211060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101221020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101221100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101611010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101611040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100611010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101611060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101631060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101711030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100721010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101721040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101721070
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101741030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100411010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100411030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101411080
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101411100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101411110
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101421100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101441010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100511030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101511050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101511060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100511050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101511090
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101521040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101531010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101014030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101024030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101024040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101334030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101334040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101214010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101224010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100514020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101514030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101534010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100012010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101112010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101122020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101222010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101722010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101422010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900111010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900311010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900314010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900311030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900334010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900334020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900211020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900211050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900711030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900511010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900511020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900511030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 900031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103211050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107441020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100611020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100611040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100611050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100711010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100821020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101111060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101141030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101221090
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101231030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101311090
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101311100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101341020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101511100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101521050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101541010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101541030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101611130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101611140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101621020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101621030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101621060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101621070
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101641010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101641030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101721100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102111040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102121010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102341010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102431010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102521010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102621010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103541010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103611060
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104141010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104331020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104411020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104631020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104641010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105211020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105211030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106011010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106141010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107541010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107821030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107831010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 701141010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 701541010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 701641010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 703441010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810122010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810134010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810011010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810011020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810234010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810334010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810324010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810421010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810424010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810441010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810041010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810033010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810441020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810531010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810531020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810521010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810621010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810611010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810011030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810041020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810611020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810621020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810641010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810631010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810641020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810713010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810732010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810741010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810741020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810821010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810821020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820331010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820531010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820844010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820844020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810021010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820531020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820843010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820341010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820844030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820541010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820843020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820844040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810014010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 810034010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820243010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820231010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820044010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820441010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 820843030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 127141030
|
||||||
|
}
|
||||||
|
]
|
||||||
1
SVSim.Bootstrap/Data/seeds/maintenance-cards.json
Normal file
1
SVSim.Bootstrap/Data/seeds/maintenance-cards.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 119,
|
||||||
|
"period_num": 118,
|
||||||
|
"necessary_score": 0,
|
||||||
|
"begin_time": "2026-05-01 02:00:00",
|
||||||
|
"end_time": "2026-06-01 01:59:59"
|
||||||
|
}
|
||||||
|
]
|
||||||
74
SVSim.Bootstrap/Data/seeds/my-rotation-abilities.json
Normal file
74
SVSim.Bootstrap/Data/seeds/my-rotation-abilities.json
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "1",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "2",
|
||||||
|
"increase_add_pptotal_turn": "40",
|
||||||
|
"ability": "",
|
||||||
|
"ability_desc": "At the start of turns you can evolve, gain 2 play point orbs."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "2",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "0",
|
||||||
|
"increase_add_pptotal_turn": "0",
|
||||||
|
"ability": "(skill:possess_ep_modifier)(timing:self_turn_start)(condition:{me.usable_ep}<=0&&evolvable_turn=true)(target:character=me&target=inplay&card_type=class)(option:add_ep=2)(preprocess:remove_after_action=(count=1))(effect_path:btl_ep_cure_1)(se_path:se_btl_ep_cure_1)(effect_move_type:DIRECT_EPPANEL_SELF)(engine_type:SHURIKEN)(effect_time:0.5)(effect_target_type:single)",
|
||||||
|
"ability_desc": "At the start of turns you can evolve, if you have 0 evolution points, recover 2. [1 time]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "3",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "0",
|
||||||
|
"increase_add_pptotal_turn": "0",
|
||||||
|
"ability": "(skill:draw)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:character=me&target=deck&card_type=all&random_count=2)(option:none)(preprocess:remove_after_action=(count=1))",
|
||||||
|
"ability_desc": "At the start of your first turn, draw 2 cards."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "4",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "1",
|
||||||
|
"increase_add_pptotal_turn": "40",
|
||||||
|
"ability": "",
|
||||||
|
"ability_desc": "At the start of turns you can evolve, gain a play point orb."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "5",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "0",
|
||||||
|
"increase_add_pptotal_turn": "0",
|
||||||
|
"ability": "(skill:possess_ep_modifier)(timing:self_turn_start)(condition:{me.usable_ep}<=0&&evolvable_turn=true)(target:character=me&target=inplay&card_type=class)(option:add_ep=1)(preprocess:remove_after_action=(count=1))(effect_path:btl_ep_cure_1)(se_path:se_btl_ep_cure_1)(effect_move_type:DIRECT_EPPANEL_SELF)(engine_type:SHURIKEN)(effect_time:0.5)(effect_target_type:single)",
|
||||||
|
"ability_desc": "At the start of turns you can evolve, if you have 0 evolution points, recover 1. [1 time]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"data": {
|
||||||
|
"ability_id": "6",
|
||||||
|
"add_start_pp": "0",
|
||||||
|
"add_start_life": "0",
|
||||||
|
"increase_add_pptotal_amount": "0",
|
||||||
|
"increase_add_pptotal_turn": "0",
|
||||||
|
"ability": "(skill:draw)(timing:self_turn_start)(condition:{me.inplay.class.turn}=1)(target:character=me&target=deck&card_type=all&random_count=1)(option:none)(preprocess:remove_after_action=(count=1))",
|
||||||
|
"ability_desc": "At the start of your first turn, draw a card."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
10
SVSim.Bootstrap/Data/seeds/my-rotation-schedule.json
Normal file
10
SVSim.Bootstrap/Data/seeds/my-rotation-schedule.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"gathering": {
|
||||||
|
"begin": "2024-05-01 20:00:00",
|
||||||
|
"end": "2030-06-26 19:59:59"
|
||||||
|
},
|
||||||
|
"free_battle": {
|
||||||
|
"begin": "2024-05-01 20:00:00",
|
||||||
|
"end": "2030-06-26 19:59:59"
|
||||||
|
}
|
||||||
|
}
|
||||||
191
SVSim.Bootstrap/Data/seeds/my-rotation-settings.json
Normal file
191
SVSim.Bootstrap/Data/seeds/my-rotation-settings.json
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 10006,
|
||||||
|
"card_set_ids_csv": "10000|10001|10002|10003|10004|10005|10006",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101114050\": 101114050, \"101141020\": 101141020, \"101241010\": 101241010, \"101314020\": 101314020, \"101341020\": 101341020, \"101431030\": 101431030, \"101441020\": 101441020, \"101514010\": 101514010, \"101541010\": 101541010, \"101614020\": 101614020, \"101641010\": 101641010, \"101741030\": 101741030, \"102312040\": 102312040, \"103241010\": 103241010, \"103541010\": 103541010, \"104141020\": 104141020, \"104341020\": 104341020, \"104441010\": 104441010, \"104641010\": 104641010, \"104741020\": 104741020, \"105312010\": 105312010, \"106114010\": 106114010, \"106221010\": 106221010, \"106324010\": 106324010, \"106434010\": 106434010, \"106511010\": 106511010, \"106624010\": 106624010, \"106721030\": 106721030}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10007,
|
||||||
|
"card_set_ids_csv": "10000|10003|10004|10005|10006|10007",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"103241010\": 103241010, \"103541010\": 103541010, \"104141020\": 104141020, \"104341020\": 104341020, \"104441010\": 104441010, \"104641010\": 104641010, \"104741020\": 104741020, \"105312010\": 105312010, \"106114010\": 106114010, \"106221010\": 106221010, \"106324010\": 106324010, \"106434010\": 106434010, \"106511010\": 106511010, \"106624010\": 106624010, \"106721030\": 106721030, \"107322010\": 107322010, \"107732010\": 107732010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10008,
|
||||||
|
"card_set_ids_csv": "10000|10004|10005|10006|10007|10008",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101614020\": 101614020, \"104141020\": 104141020, \"104341020\": 104341020, \"104441010\": 104441010, \"104641010\": 104641010, \"104741020\": 104741020, \"105312010\": 105312010, \"106114010\": 106114010, \"106221010\": 106221010, \"106324010\": 106324010, \"106434010\": 106434010, \"106511010\": 106511010, \"106624010\": 106624010, \"106721030\": 106721030, \"107322010\": 107322010, \"107732010\": 107732010, \"108031020\": 108031020}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10009,
|
||||||
|
"card_set_ids_csv": "10000|10005|10006|10007|10008|10009",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101314020\": 101314020, \"101514010\": 101514010, \"101614020\": 101614020, \"105312010\": 105312010, \"106114010\": 106114010, \"106221010\": 106221010, \"106324010\": 106324010, \"106434010\": 106434010, \"106511010\": 106511010, \"106624010\": 106624010, \"106721030\": 106721030, \"107322010\": 107322010, \"107732010\": 107732010, \"108031020\": 108031020, \"109034010\": 109034010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10010,
|
||||||
|
"card_set_ids_csv": "10000|10006|10007|10008|10009|10010",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114050\": 101114050, \"101314020\": 101314020, \"101514010\": 101514010, \"101614020\": 101614020, \"102312040\": 102312040, \"106114010\": 106114010, \"106221010\": 106221010, \"106324010\": 106324010, \"106434010\": 106434010, \"106511010\": 106511010, \"106624010\": 106624010, \"106721030\": 106721030, \"107322010\": 107322010, \"107732010\": 107732010, \"108031020\": 108031020, \"109034010\": 109034010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10011,
|
||||||
|
"card_set_ids_csv": "10000|10007|10008|10009|10010|10011",
|
||||||
|
"abilities_csv": "1|2|3",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114050\": 101114050, \"101314020\": 101314020, \"101514010\": 101514010, \"101614020\": 101614020, \"102312040\": 102312040, \"107322010\": 107322010, \"107732010\": 107732010, \"108031020\": 108031020, \"109034010\": 109034010, \"111124010\": 111124010, \"111214010\": 111214010, \"111314010\": 111314010, \"111434010\": 111434010, \"111514010\": 111514010, \"111634010\": 111634010, \"111734010\": 111734010, \"111814010\": 111814010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10012,
|
||||||
|
"card_set_ids_csv": "10000|10008|10009|10010|10011|10012",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101114050\": 101114050, \"101314020\": 101314020, \"101514010\": 101514010, \"101614020\": 101614020, \"102312040\": 102312040, \"108031020\": 108031020, \"109034010\": 109034010, \"111124010\": 111124010, \"111214010\": 111214010, \"111314010\": 111314010, \"111434010\": 111434010, \"111514010\": 111514010, \"111634010\": 111634010, \"111734010\": 111734010, \"111814010\": 111814010, \"112031010\": 112031010, \"112122010\": 112122010, \"112222010\": 112222010, \"112224010\": 112224010, \"112322010\": 112322010, \"112414010\": 112414010, \"112422010\": 112422010, \"112522010\": 112522010, \"112622010\": 112622010, \"112722010\": 112722010, \"112822010\": 112822010, \"112834010\": 112834010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10013,
|
||||||
|
"card_set_ids_csv": "10000|10009|10010|10011|10012|10013",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101114050\": 101114050, \"101314020\": 101314020, \"101514010\": 101514010, \"102312040\": 102312040, \"105312010\": 105312010, \"109034010\": 109034010, \"111124010\": 111124010, \"111214010\": 111214010, \"111314010\": 111314010, \"111434010\": 111434010, \"111514010\": 111514010, \"111634010\": 111634010, \"111734010\": 111734010, \"111814010\": 111814010, \"112031010\": 112031010, \"112122010\": 112122010, \"112222010\": 112222010, \"112224010\": 112224010, \"112322010\": 112322010, \"112414010\": 112414010, \"112422010\": 112422010, \"112522010\": 112522010, \"112622010\": 112622010, \"112722010\": 112722010, \"112822010\": 112822010, \"112834010\": 112834010, \"113034010\": 113034010, \"113114010\": 113114010, \"113224010\": 113224010, \"113614010\": 113614010, \"113733010\": 113733010, \"113824010\": 113824010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10014,
|
||||||
|
"card_set_ids_csv": "10000|10010|10011|10012|10013|10014",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101114050\": 101114050, \"102312040\": 102312040, \"105312010\": 105312010, \"106114010\": 106114010, \"107322010\": 107322010, \"111124010\": 111124010, \"111214010\": 111214010, \"111314010\": 111314010, \"111434010\": 111434010, \"111514010\": 111514010, \"111634010\": 111634010, \"111734010\": 111734010, \"111814010\": 111814010, \"112031010\": 112031010, \"112122010\": 112122010, \"112222010\": 112222010, \"112224010\": 112224010, \"112322010\": 112322010, \"112414010\": 112414010, \"112422010\": 112422010, \"112522010\": 112522010, \"112622010\": 112622010, \"112722010\": 112722010, \"112822010\": 112822010, \"112834010\": 112834010, \"113034010\": 113034010, \"113114010\": 113114010, \"113224010\": 113224010, \"113614010\": 113614010, \"113733010\": 113733010, \"113824010\": 113824010, \"114014010\": 114014010, \"114031010\": 114031010, \"114234010\": 114234010, \"114834010\": 114834010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10015,
|
||||||
|
"card_set_ids_csv": "10000|10011|10012|10013|10014|10015",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"105312010\": 105312010, \"106114010\": 106114010, \"107322010\": 107322010, \"111124010\": 111124010, \"111214010\": 111214010, \"111314010\": 111314010, \"111434010\": 111434010, \"111514010\": 111514010, \"111634010\": 111634010, \"111734010\": 111734010, \"111814010\": 111814010, \"112031010\": 112031010, \"112122010\": 112122010, \"112222010\": 112222010, \"112224010\": 112224010, \"112322010\": 112322010, \"112414010\": 112414010, \"112422010\": 112422010, \"112522010\": 112522010, \"112622010\": 112622010, \"112722010\": 112722010, \"112822010\": 112822010, \"112834010\": 112834010, \"113034010\": 113034010, \"113114010\": 113114010, \"113224010\": 113224010, \"113614010\": 113614010, \"113733010\": 113733010, \"113824010\": 113824010, \"114014010\": 114014010, \"114031010\": 114031010, \"114234010\": 114234010, \"114834010\": 114834010, \"115124010\": 115124010, \"115214010\": 115214010, \"115414010\": 115414010, \"115814010\": 115814010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10016,
|
||||||
|
"card_set_ids_csv": "10000|10012|10013|10014|10015|10016",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"105312010\": 105312010, \"106114010\": 106114010, \"107322010\": 107322010, \"112031010\": 112031010, \"112122010\": 112122010, \"112222010\": 112222010, \"112224010\": 112224010, \"112322010\": 112322010, \"112414010\": 112414010, \"112422010\": 112422010, \"112522010\": 112522010, \"112622010\": 112622010, \"112722010\": 112722010, \"112822010\": 112822010, \"112834010\": 112834010, \"113034010\": 113034010, \"113114010\": 113114010, \"113224010\": 113224010, \"113614010\": 113614010, \"113733010\": 113733010, \"113824010\": 113824010, \"114014010\": 114014010, \"114031010\": 114031010, \"114234010\": 114234010, \"114834010\": 114834010, \"115124010\": 115124010, \"115214010\": 115214010, \"115414010\": 115414010, \"115814010\": 115814010, \"116524010\": 116524010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10017,
|
||||||
|
"card_set_ids_csv": "10000|10013|10014|10015|10016|10017",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"105312010\": 105312010, \"106114010\": 106114010, \"107322010\": 107322010, \"113034010\": 113034010, \"113114010\": 113114010, \"113224010\": 113224010, \"113614010\": 113614010, \"113733010\": 113733010, \"113824010\": 113824010, \"114014010\": 114014010, \"114031010\": 114031010, \"114234010\": 114234010, \"114834010\": 114834010, \"115124010\": 115124010, \"115214010\": 115214010, \"115414010\": 115414010, \"115814010\": 115814010, \"116524010\": 116524010, \"117034010\": 117034010, \"117124010\": 117124010, \"117234010\": 117234010, \"117434010\": 117434010, \"117624010\": 117624010, \"117724010\": 117724010, \"117824010\": 117824010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10018,
|
||||||
|
"card_set_ids_csv": "10000|10014|10015|10016|10017|10018",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"106114010\": 106114010, \"107322010\": 107322010, \"114014010\": 114014010, \"114031010\": 114031010, \"114234010\": 114234010, \"114834010\": 114834010, \"115124010\": 115124010, \"115214010\": 115214010, \"115414010\": 115414010, \"115814010\": 115814010, \"116524010\": 116524010, \"117034010\": 117034010, \"117124010\": 117124010, \"117234010\": 117234010, \"117434010\": 117434010, \"117624010\": 117624010, \"117724010\": 117724010, \"117824010\": 117824010, \"118011020\": 118011020, \"118424010\": 118424010, \"118524010\": 118524010, \"118531010\": 118531010, \"118624010\": 118624010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10019,
|
||||||
|
"card_set_ids_csv": "10000|10015|10016|10017|10018|10019",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"107732010\": 107732010, \"115124010\": 115124010, \"115214010\": 115214010, \"115414010\": 115414010, \"115814010\": 115814010, \"116524010\": 116524010, \"117034010\": 117034010, \"117124010\": 117124010, \"117234010\": 117234010, \"117434010\": 117434010, \"117624010\": 117624010, \"117724010\": 117724010, \"117824010\": 117824010, \"118011020\": 118011020, \"118424010\": 118424010, \"118524010\": 118524010, \"118531010\": 118531010, \"118624010\": 118624010, \"119031030\": 119031030, \"119314010\": 119314010, \"119424010\": 119424010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10020,
|
||||||
|
"card_set_ids_csv": "10000|10016|10017|10018|10019|10020",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"107732010\": 107732010, \"116524010\": 116524010, \"117034010\": 117034010, \"117124010\": 117124010, \"117234010\": 117234010, \"117434010\": 117434010, \"117624010\": 117624010, \"117724010\": 117724010, \"117824010\": 117824010, \"118011020\": 118011020, \"118424010\": 118424010, \"118524010\": 118524010, \"118531010\": 118531010, \"118624010\": 118624010, \"119031030\": 119031030, \"119314010\": 119314010, \"119424010\": 119424010, \"120014010\": 120014010, \"120134010\": 120134010, \"120214010\": 120214010, \"120221020\": 120221020, \"120611010\": 120611010, \"120721020\": 120721020, \"120821020\": 120821020}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10021,
|
||||||
|
"card_set_ids_csv": "10000|10017|10018|10019|10020|10021",
|
||||||
|
"abilities_csv": "4|5|6",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"107732010\": 107732010, \"117034010\": 117034010, \"117124010\": 117124010, \"117234010\": 117234010, \"117434010\": 117434010, \"117624010\": 117624010, \"117724010\": 117724010, \"117824010\": 117824010, \"118011020\": 118011020, \"118424010\": 118424010, \"118524010\": 118524010, \"118531010\": 118531010, \"118624010\": 118624010, \"119031030\": 119031030, \"119314010\": 119314010, \"119424010\": 119424010, \"120014010\": 120014010, \"120134010\": 120134010, \"120214010\": 120214010, \"120221020\": 120221020, \"120611010\": 120611010, \"120721020\": 120721020, \"120821020\": 120821020, \"121031010\": 121031010, \"121221010\": 121221010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10022,
|
||||||
|
"card_set_ids_csv": "10000|10018|10019|10020|10021|10022",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"107732010\": 107732010, \"118011020\": 118011020, \"118424010\": 118424010, \"118524010\": 118524010, \"118531010\": 118531010, \"118624010\": 118624010, \"119031030\": 119031030, \"119314010\": 119314010, \"119424010\": 119424010, \"120014010\": 120014010, \"120134010\": 120134010, \"120214010\": 120214010, \"120221020\": 120221020, \"120611010\": 120611010, \"120721020\": 120721020, \"120821020\": 120821020, \"121031010\": 121031010, \"121221010\": 121221010, \"122121030\": 122121030, \"122334010\": 122334010, \"122514010\": 122514010, \"122714010\": 122714010, \"122811020\": 122811020}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10023,
|
||||||
|
"card_set_ids_csv": "10000|10019|10020|10021|10022|10023",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"107732010\": 107732010, \"119031030\": 119031030, \"119314010\": 119314010, \"119424010\": 119424010, \"120014010\": 120014010, \"120134010\": 120134010, \"120214010\": 120214010, \"120221020\": 120221020, \"120611010\": 120611010, \"120721020\": 120721020, \"120821020\": 120821020, \"121031010\": 121031010, \"121221010\": 121221010, \"122121030\": 122121030, \"122334010\": 122334010, \"122514010\": 122514010, \"122714010\": 122714010, \"122811020\": 122811020, \"123114010\": 123114010, \"123231010\": 123231010, \"123314010\": 123314010, \"123331020\": 123331020, \"123414010\": 123414010, \"123514010\": 123514010, \"123614010\": 123614010, \"123814010\": 123814010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10024,
|
||||||
|
"card_set_ids_csv": "10000|10020|10021|10022|10023|10024",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"120014010\": 120014010, \"120134010\": 120134010, \"120214010\": 120214010, \"120221020\": 120221020, \"120611010\": 120611010, \"120721020\": 120721020, \"120821020\": 120821020, \"121031010\": 121031010, \"121221010\": 121221010, \"122121030\": 122121030, \"122334010\": 122334010, \"122514010\": 122514010, \"122714010\": 122714010, \"122811020\": 122811020, \"123114010\": 123114010, \"123231010\": 123231010, \"123314010\": 123314010, \"123331020\": 123331020, \"123414010\": 123414010, \"123514010\": 123514010, \"123614010\": 123614010, \"123814010\": 123814010, \"124024010\": 124024010, \"124121020\": 124121020, \"124131010\": 124131010, \"124134010\": 124134010, \"124214010\": 124214010, \"124221020\": 124221020, \"124324010\": 124324010, \"124421020\": 124421020, \"124524010\": 124524010, \"124624010\": 124624010, \"124721020\": 124721020, \"124731010\": 124731010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10025,
|
||||||
|
"card_set_ids_csv": "10000|10021|10022|10023|10024|10025",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"121031010\": 121031010, \"121221010\": 121221010, \"122121030\": 122121030, \"122334010\": 122334010, \"122514010\": 122514010, \"122714010\": 122714010, \"122811020\": 122811020, \"123114010\": 123114010, \"123231010\": 123231010, \"123314010\": 123314010, \"123331020\": 123331020, \"123414010\": 123414010, \"123514010\": 123514010, \"123614010\": 123614010, \"123814010\": 123814010, \"124024010\": 124024010, \"124121020\": 124121020, \"124131010\": 124131010, \"124134010\": 124134010, \"124214010\": 124214010, \"124221020\": 124221020, \"124324010\": 124324010, \"124421020\": 124421020, \"124524010\": 124524010, \"124624010\": 124624010, \"124721020\": 124721020, \"124731010\": 124731010, \"125011010\": 125011010, \"125414010\": 125414010, \"125614010\": 125614010, \"125733010\": 125733010, \"125811030\": 125811030, \"125834010\": 125834010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10026,
|
||||||
|
"card_set_ids_csv": "10000|10022|10023|10024|10025|10026",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"122121030\": 122121030, \"122334010\": 122334010, \"122514010\": 122514010, \"122714010\": 122714010, \"122811020\": 122811020, \"123114010\": 123114010, \"123231010\": 123231010, \"123314010\": 123314010, \"123331020\": 123331020, \"123414010\": 123414010, \"123514010\": 123514010, \"123614010\": 123614010, \"123814010\": 123814010, \"124024010\": 124024010, \"124121020\": 124121020, \"124131010\": 124131010, \"124134010\": 124134010, \"124214010\": 124214010, \"124221020\": 124221020, \"124324010\": 124324010, \"124421020\": 124421020, \"124524010\": 124524010, \"124624010\": 124624010, \"124721020\": 124721020, \"124731010\": 124731010, \"125011010\": 125011010, \"125414010\": 125414010, \"125614010\": 125614010, \"125733010\": 125733010, \"125811030\": 125811030, \"125834010\": 125834010, \"126031020\": 126031020, \"126114010\": 126114010, \"126234010\": 126234010, \"126334010\": 126334010, \"126411030\": 126411030, \"126424010\": 126424010, \"126514010\": 126514010, \"126521020\": 126521020, \"126614010\": 126614010, \"126732010\": 126732010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10027,
|
||||||
|
"card_set_ids_csv": "10000|10023|10024|10025|10026|10027",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"123114010\": 123114010, \"123231010\": 123231010, \"123314010\": 123314010, \"123331020\": 123331020, \"123414010\": 123414010, \"123514010\": 123514010, \"123614010\": 123614010, \"123814010\": 123814010, \"124024010\": 124024010, \"124121020\": 124121020, \"124131010\": 124131010, \"124134010\": 124134010, \"124214010\": 124214010, \"124221020\": 124221020, \"124324010\": 124324010, \"124421020\": 124421020, \"124524010\": 124524010, \"124624010\": 124624010, \"124721020\": 124721020, \"124731010\": 124731010, \"125011010\": 125011010, \"125414010\": 125414010, \"125614010\": 125614010, \"125733010\": 125733010, \"125811030\": 125811030, \"125834010\": 125834010, \"126031020\": 126031020, \"126114010\": 126114010, \"126234010\": 126234010, \"126334010\": 126334010, \"126411030\": 126411030, \"126424010\": 126424010, \"126514010\": 126514010, \"126521020\": 126521020, \"126614010\": 126614010, \"126732010\": 126732010, \"127134010\": 127134010, \"127141030\": 127141030, \"127314010\": 127314010, \"127614010\": 127614010, \"127713010\": 127713010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10028,
|
||||||
|
"card_set_ids_csv": "10000|10024|10025|10026|10027|10028",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"124024010\": 124024010, \"124121020\": 124121020, \"124131010\": 124131010, \"124134010\": 124134010, \"124214010\": 124214010, \"124221020\": 124221020, \"124324010\": 124324010, \"124421020\": 124421020, \"124524010\": 124524010, \"124624010\": 124624010, \"124721020\": 124721020, \"124731010\": 124731010, \"125011010\": 125011010, \"125414010\": 125414010, \"125614010\": 125614010, \"125733010\": 125733010, \"125811030\": 125811030, \"125834010\": 125834010, \"126031020\": 126031020, \"126114010\": 126114010, \"126234010\": 126234010, \"126334010\": 126334010, \"126411030\": 126411030, \"126424010\": 126424010, \"126514010\": 126514010, \"126521020\": 126521020, \"126614010\": 126614010, \"126732010\": 126732010, \"127134010\": 127134010, \"127141030\": 127141030, \"127314010\": 127314010, \"127614010\": 127614010, \"127713010\": 127713010, \"128224010\": 128224010, \"128424010\": 128424010, \"128514010\": 128514010, \"128614010\": 128614010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10029,
|
||||||
|
"card_set_ids_csv": "10000|10025|10026|10027|10028|10029",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"125011010\": 125011010, \"125414010\": 125414010, \"125614010\": 125614010, \"125733010\": 125733010, \"125811030\": 125811030, \"125834010\": 125834010, \"126031020\": 126031020, \"126114010\": 126114010, \"126234010\": 126234010, \"126334010\": 126334010, \"126411030\": 126411030, \"126424010\": 126424010, \"126514010\": 126514010, \"126521020\": 126521020, \"126614010\": 126614010, \"126732010\": 126732010, \"127134010\": 127134010, \"127141030\": 127141030, \"127314010\": 127314010, \"127614010\": 127614010, \"127713010\": 127713010, \"128224010\": 128224010, \"128424010\": 128424010, \"128514010\": 128514010, \"128614010\": 128614010, \"129024010\": 129024010, \"129211010\": 129211010, \"129214010\": 129214010, \"129314020\": 129314020, \"129321010\": 129321010, \"129421010\": 129421010, \"129713020\": 129713020}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10030,
|
||||||
|
"card_set_ids_csv": "10000|10026|10027|10028|10029|10030",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101314020\": 101314020, \"126031020\": 126031020, \"126114010\": 126114010, \"126234010\": 126234010, \"126334010\": 126334010, \"126411030\": 126411030, \"126424010\": 126424010, \"126514010\": 126514010, \"126521020\": 126521020, \"126614010\": 126614010, \"126732010\": 126732010, \"127134010\": 127134010, \"127141030\": 127141030, \"127314010\": 127314010, \"127614010\": 127614010, \"127713010\": 127713010, \"128224010\": 128224010, \"128424010\": 128424010, \"128514010\": 128514010, \"128614010\": 128614010, \"129024010\": 129024010, \"129211010\": 129211010, \"129214010\": 129214010, \"129314020\": 129314020, \"129321010\": 129321010, \"129421010\": 129421010, \"129713020\": 129713020, \"130024010\": 130024010, \"130141020\": 130141020, \"130241020\": 130241020, \"130341020\": 130341020, \"130641020\": 130641020}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10031,
|
||||||
|
"card_set_ids_csv": "10000|10027|10028|10029|10030|10031",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101314020\": 101314020, \"127134010\": 127134010, \"127141030\": 127141030, \"127314010\": 127314010, \"127614010\": 127614010, \"127713010\": 127713010, \"128224010\": 128224010, \"128424010\": 128424010, \"128514010\": 128514010, \"128614010\": 128614010, \"129024010\": 129024010, \"129211010\": 129211010, \"129214010\": 129214010, \"129314020\": 129314020, \"129321010\": 129321010, \"129421010\": 129421010, \"129713020\": 129713020, \"130024010\": 130024010, \"130141020\": 130141020, \"130241020\": 130241020, \"130341020\": 130341020, \"130641020\": 130641020, \"131031020\": 131031020, \"131723010\": 131723010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10032,
|
||||||
|
"card_set_ids_csv": "10000|10028|10029|10030|10031|10032",
|
||||||
|
"abilities_csv": "",
|
||||||
|
"reprinted_card_ids": "{\"100114010\": 100114010, \"100211010\": 100211010, \"100214010\": 100214010, \"100214020\": 100214020, \"100314010\": 100314010, \"100314020\": 100314020, \"100314030\": 100314030, \"100314040\": 100314040, \"100314070\": 100314070, \"100414010\": 100414010, \"100514010\": 100514010, \"100614010\": 100614010, \"100614020\": 100614020, \"100714010\": 100714010, \"100714020\": 100714020, \"100814010\": 100814010, \"101114010\": 101114010, \"101314020\": 101314020, \"128224010\": 128224010, \"128424010\": 128424010, \"128514010\": 128514010, \"128614010\": 128614010, \"129024010\": 129024010, \"129211010\": 129211010, \"129214010\": 129214010, \"129314020\": 129314020, \"129321010\": 129321010, \"129421010\": 129421010, \"129713020\": 129713020, \"130024010\": 130024010, \"130141020\": 130141020, \"130241020\": 130241020, \"130341020\": 130341020, \"130641020\": 130641020, \"131031020\": 131031020, \"131723010\": 131723010}",
|
||||||
|
"restricted_card_ids": "{\"123041020\": \"0\"}"
|
||||||
|
}
|
||||||
|
]
|
||||||
2808
SVSim.Bootstrap/Data/seeds/packs.json
Normal file
2808
SVSim.Bootstrap/Data/seeds/packs.json
Normal file
File diff suppressed because it is too large
Load Diff
182
SVSim.Bootstrap/Data/seeds/payment-items.json
Normal file
182
SVSim.Bootstrap/Data/seeds/payment-items.json
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"record_id": 3,
|
||||||
|
"product_id": 992,
|
||||||
|
"store_product_id": 99200,
|
||||||
|
"name": "[b]One-time Deal![/b] 800-crystal set",
|
||||||
|
"text": "Purchase 800 Crystals",
|
||||||
|
"price": "7.99",
|
||||||
|
"charge_crystal_num": 800,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 1,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal_strong",
|
||||||
|
"start_time": "2018-01-30 04:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 10,
|
||||||
|
"product_id": 994,
|
||||||
|
"store_product_id": 99400,
|
||||||
|
"name": "[b]Special Offer![/b] 7500-crystal set (3 times per person)",
|
||||||
|
"text": "Purchase 7500 Crystals",
|
||||||
|
"price": "79.99",
|
||||||
|
"charge_crystal_num": 7500,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 3,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal_strong",
|
||||||
|
"start_time": "2017-06-01 06:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 19,
|
||||||
|
"product_id": 989,
|
||||||
|
"store_product_id": 98900,
|
||||||
|
"name": "[b]1-Time Deal![/b] 1000-crystal set",
|
||||||
|
"text": "Purchase 1000 Crystals",
|
||||||
|
"price": "15.99",
|
||||||
|
"charge_crystal_num": 1000,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 1,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal_strong",
|
||||||
|
"start_time": "2026-04-01 02:00:00",
|
||||||
|
"end_time": "2026-07-01 01:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 1,
|
||||||
|
"resale_start_date": "2026-04-01 02:00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 21,
|
||||||
|
"product_id": 8,
|
||||||
|
"store_product_id": 10011,
|
||||||
|
"name": "60-crystal set",
|
||||||
|
"text": "Purchase 60 Crystals",
|
||||||
|
"price": "0.99",
|
||||||
|
"charge_crystal_num": 60,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2022-10-05 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 24,
|
||||||
|
"product_id": 9,
|
||||||
|
"store_product_id": 70011,
|
||||||
|
"name": "350-crystal set",
|
||||||
|
"text": "Purchase 350 Crystals",
|
||||||
|
"price": "5.99",
|
||||||
|
"charge_crystal_num": 350,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2022-10-05 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 26,
|
||||||
|
"product_id": 10,
|
||||||
|
"store_product_id": 30011,
|
||||||
|
"name": "670-crystal set",
|
||||||
|
"text": "Purchase 670 Crystals",
|
||||||
|
"price": "10.99",
|
||||||
|
"charge_crystal_num": 670,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2022-10-05 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 27,
|
||||||
|
"product_id": 4,
|
||||||
|
"store_product_id": 40000,
|
||||||
|
"name": "1200-crystal set",
|
||||||
|
"text": "Purchase 1200 Crystals",
|
||||||
|
"price": "20.99",
|
||||||
|
"charge_crystal_num": 1200,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2015-03-01 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 28,
|
||||||
|
"product_id": 5,
|
||||||
|
"store_product_id": 50000,
|
||||||
|
"name": "2400-crystal set",
|
||||||
|
"text": "Purchase 2400 Crystals",
|
||||||
|
"price": "39.99",
|
||||||
|
"charge_crystal_num": 2400,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2015-03-01 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 29,
|
||||||
|
"product_id": 6,
|
||||||
|
"store_product_id": 60000,
|
||||||
|
"name": "5000-crystal set",
|
||||||
|
"text": "Purchase 5000 Crystals",
|
||||||
|
"price": "79.99",
|
||||||
|
"charge_crystal_num": 5000,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 999999999,
|
||||||
|
"special_shop_flag": 0,
|
||||||
|
"image_name": "thumbnail_crystal",
|
||||||
|
"start_time": "2015-03-01 15:00:00",
|
||||||
|
"end_time": "2030-03-01 14:59:59",
|
||||||
|
"remaining_time": 0,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"record_id": 30,
|
||||||
|
"product_id": 800,
|
||||||
|
"store_product_id": 80000,
|
||||||
|
"name": "1200-crystal and Legendary set",
|
||||||
|
"text": "Purchase 1200 Crystals and Legendary set",
|
||||||
|
"price": "20.99",
|
||||||
|
"charge_crystal_num": 1200,
|
||||||
|
"free_crystal_num": 0,
|
||||||
|
"purchase_limit": 3,
|
||||||
|
"special_shop_flag": 1,
|
||||||
|
"image_name": "thumbnail_crystal_strong",
|
||||||
|
"start_time": "2018-01-01 00:00:00",
|
||||||
|
"end_time": "2019-03-19 16:15:17",
|
||||||
|
"remaining_time": 604800,
|
||||||
|
"is_resale_product": 0,
|
||||||
|
"resale_start_date": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
1367
SVSim.Bootstrap/Data/seeds/practice-opponents.json
Normal file
1367
SVSim.Bootstrap/Data/seeds/practice-opponents.json
Normal file
File diff suppressed because it is too large
Load Diff
72
SVSim.Bootstrap/Data/seeds/pre-release-info.json
Normal file
72
SVSim.Bootstrap/Data/seeds/pre-release-info.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"pre_release_id": "1",
|
||||||
|
"next_card_set_id": "10018",
|
||||||
|
"start_time": "1900-12-28 00:00:00",
|
||||||
|
"end_time": "2019-09-29 05:29:59",
|
||||||
|
"display_end_time": "2020-10-03 14:59:59",
|
||||||
|
"free_match_start_time": "1900-12-28 02:00:00",
|
||||||
|
"card_master_id": 1,
|
||||||
|
"default_card_master_id": "2",
|
||||||
|
"pre_release_card_master_id": "1",
|
||||||
|
"is_pre_rotation_free_match_term": false,
|
||||||
|
"rotation_card_set_id_list": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"reprinted_base_card_ids": {
|
||||||
|
"100114010": "100114010",
|
||||||
|
"100211010": "100211010",
|
||||||
|
"100214010": "100214010",
|
||||||
|
"100214020": "100214020",
|
||||||
|
"100314010": "100314010",
|
||||||
|
"100314020": "100314020",
|
||||||
|
"100314030": "100314030",
|
||||||
|
"100314040": "100314040",
|
||||||
|
"100314070": "100314070",
|
||||||
|
"100414010": "100414010",
|
||||||
|
"100514010": "100514010",
|
||||||
|
"100614010": "100614010",
|
||||||
|
"100614020": "100614020",
|
||||||
|
"100714010": "100714010",
|
||||||
|
"100714020": "100714020",
|
||||||
|
"100814010": "100814010",
|
||||||
|
"101114010": "101114010",
|
||||||
|
"105312010": "105312010",
|
||||||
|
"106114010": "106114010",
|
||||||
|
"107322010": "107322010",
|
||||||
|
"111124010": "111124010",
|
||||||
|
"111214010": "111214010",
|
||||||
|
"111314010": "111314010",
|
||||||
|
"111434010": "111434010",
|
||||||
|
"111514010": "111514010",
|
||||||
|
"111634010": "111634010",
|
||||||
|
"111734010": "111734010",
|
||||||
|
"111814010": "111814010",
|
||||||
|
"112031010": "112031010",
|
||||||
|
"112122010": "112122010",
|
||||||
|
"112222010": "112222010",
|
||||||
|
"112224010": "112224010",
|
||||||
|
"112322010": "112322010",
|
||||||
|
"112414010": "112414010",
|
||||||
|
"112422010": "112422010",
|
||||||
|
"112522010": "112522010",
|
||||||
|
"112622010": "112622010",
|
||||||
|
"112722010": "112722010",
|
||||||
|
"112822010": "112822010",
|
||||||
|
"112834010": "112834010",
|
||||||
|
"113034010": "113034010",
|
||||||
|
"113114010": "113114010",
|
||||||
|
"113224010": "113224010",
|
||||||
|
"113614010": "113614010",
|
||||||
|
"113733010": "113733010",
|
||||||
|
"113824010": "113824010",
|
||||||
|
"114014010": "114014010",
|
||||||
|
"114031010": "114031010",
|
||||||
|
"114234010": "114234010",
|
||||||
|
"114834010": "114834010",
|
||||||
|
"115124010": "115124010",
|
||||||
|
"115214010": "115214010",
|
||||||
|
"115414010": "115414010",
|
||||||
|
"115814010": "115814010"
|
||||||
|
},
|
||||||
|
"latest_reprinted_base_card_ids": []
|
||||||
|
}
|
||||||
305
SVSim.Bootstrap/Data/seeds/puzzle-groups.json
Normal file
305
SVSim.Bootstrap/Data/seeds/puzzle-groups.json
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 316,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0316",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 315,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0315",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 314,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0314",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 313,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0313",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 312,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0312",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 311,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0311",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 310,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0310",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 309,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0309",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 308,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0308",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 307,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0307",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 306,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0306",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 305,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0305",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 304,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0304",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 303,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0303",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 302,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0302",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 301,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0301",
|
||||||
|
"puzzle_chara_id": 3704,
|
||||||
|
"chara_id": 3704,
|
||||||
|
"sort_type": 1,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0109",
|
||||||
|
"puzzle_chara_id": 600090,
|
||||||
|
"chara_id": 600090,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2",
|
||||||
|
"": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0108",
|
||||||
|
"puzzle_chara_id": 600080,
|
||||||
|
"chara_id": 600080,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2",
|
||||||
|
"": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0107",
|
||||||
|
"puzzle_chara_id": 600070,
|
||||||
|
"chara_id": 600070,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0106",
|
||||||
|
"puzzle_chara_id": 600060,
|
||||||
|
"chara_id": 600060,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2",
|
||||||
|
"": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0105",
|
||||||
|
"puzzle_chara_id": 3801,
|
||||||
|
"chara_id": 3801,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0104",
|
||||||
|
"puzzle_chara_id": 3603,
|
||||||
|
"chara_id": 3603,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2",
|
||||||
|
"": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0103",
|
||||||
|
"puzzle_chara_id": 3403,
|
||||||
|
"chara_id": 3403,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0102",
|
||||||
|
"puzzle_chara_id": 3208,
|
||||||
|
"chara_id": 2703,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2",
|
||||||
|
"": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"basic_title_text_id": "Puzzle_QuestSelect_0101",
|
||||||
|
"puzzle_chara_id": 600050,
|
||||||
|
"chara_id": 600050,
|
||||||
|
"sort_type": 2,
|
||||||
|
"difficulty_name_list": {
|
||||||
|
"Beginner": "0",
|
||||||
|
"Experienced": "1",
|
||||||
|
"Expert": "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
230
SVSim.Bootstrap/Data/seeds/puzzle-missions.json
Normal file
230
SVSim.Bootstrap/Data/seeds/puzzle-missions.json
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"mission_name": "Clear all Dragoncraft and Portalcraft puzzles puzzles in the Special Round",
|
||||||
|
"achieved_message": "Mission achieved",
|
||||||
|
"require_number": 2,
|
||||||
|
"campaign_commence_time": 1725670800,
|
||||||
|
"order_id": 5,
|
||||||
|
"reward_type": 4,
|
||||||
|
"reward_detail_id": 90001,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"mission_name": "Clear all Forestcraft, Shadowcraft and Bloodcraft puzzles in the Special Round",
|
||||||
|
"achieved_message": "Mission achieved",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1722646800,
|
||||||
|
"order_id": 4,
|
||||||
|
"reward_type": 4,
|
||||||
|
"reward_detail_id": 90001,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"mission_name": "Clear all Swordcraft, Runecraft and Havencraft puzzles in the Special Round",
|
||||||
|
"achieved_message": "Mission achieved",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1720227600,
|
||||||
|
"order_id": 3,
|
||||||
|
"reward_type": 4,
|
||||||
|
"reward_detail_id": 90001,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"mission_name": "Clear all Special Round puzzles",
|
||||||
|
"achieved_message": "Mission achieved",
|
||||||
|
"require_number": 8,
|
||||||
|
"campaign_commence_time": 1720227600,
|
||||||
|
"order_id": 2,
|
||||||
|
"reward_type": 7,
|
||||||
|
"reward_detail_id": 400004315,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"mission_name": "Clear all Round 15 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 15 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1716598800,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 7,
|
||||||
|
"reward_detail_id": 400004314,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 315
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"mission_name": "Clear all Round 14 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 14 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1711760400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3065004,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 314
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"mission_name": "Clear all Round 13 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 13 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1708736400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 7,
|
||||||
|
"reward_detail_id": 400004313,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 313
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"mission_name": "Clear all Round 12 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 12 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1703898000,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074009,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 312
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"mission_name": "Clear all Round 11 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 11 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1700269200,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074008,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 311
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"mission_name": "Clear all Round 10 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 10 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1692406800,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074007,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 310
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"mission_name": "Clear all Round 9 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 9 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1688173200,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074006,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 309
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"mission_name": "Clear all Round 8 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 8 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1684544400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074005,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 308
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"mission_name": "Clear all Round 7 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 7 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1677286800,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074004,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 307
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"mission_name": "Clear all Round 6 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 6 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1672448400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074003,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 306
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"mission_name": "Clear all Round 5 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 5 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1669424400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074002,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 305
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"mission_name": "Clear all Round 4 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 4 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1660959000,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 6,
|
||||||
|
"reward_detail_id": 3074001,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 304
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"mission_name": "Clear all Round 3 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 3 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1656725400,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 7,
|
||||||
|
"reward_detail_id": 400004105,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 303
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"mission_name": "Clear all Round 2 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 2 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1653096600,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 7,
|
||||||
|
"reward_detail_id": 400004104,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 302
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"mission_name": "Clear all Round 1 puzzles",
|
||||||
|
"achieved_message": "Cleared all Round 1 puzzles",
|
||||||
|
"require_number": 3,
|
||||||
|
"campaign_commence_time": 1651282200,
|
||||||
|
"order_id": 1,
|
||||||
|
"reward_type": 10,
|
||||||
|
"reward_detail_id": 3704,
|
||||||
|
"reward_number": 1,
|
||||||
|
"target_puzzle_group_id": 301
|
||||||
|
}
|
||||||
|
]
|
||||||
906
SVSim.Bootstrap/Data/seeds/puzzles.json
Normal file
906
SVSim.Bootstrap/Data/seeds/puzzles.json
Normal file
@@ -0,0 +1,906 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 106,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 107,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 108,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 109,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": true,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 110,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": true,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 111,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": true,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 112,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": true,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 113,
|
||||||
|
"group_id": 316,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": true,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 103,
|
||||||
|
"group_id": 315,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 104,
|
||||||
|
"group_id": 315,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 105,
|
||||||
|
"group_id": 315,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 100,
|
||||||
|
"group_id": 314,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 101,
|
||||||
|
"group_id": 314,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 102,
|
||||||
|
"group_id": 314,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 97,
|
||||||
|
"group_id": 313,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 98,
|
||||||
|
"group_id": 313,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 99,
|
||||||
|
"group_id": 313,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 94,
|
||||||
|
"group_id": 312,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 95,
|
||||||
|
"group_id": 312,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 96,
|
||||||
|
"group_id": 312,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 91,
|
||||||
|
"group_id": 311,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 92,
|
||||||
|
"group_id": 311,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 93,
|
||||||
|
"group_id": 311,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 84,
|
||||||
|
"group_id": 310,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 85,
|
||||||
|
"group_id": 310,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 86,
|
||||||
|
"group_id": 310,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 77,
|
||||||
|
"group_id": 309,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 78,
|
||||||
|
"group_id": 309,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 79,
|
||||||
|
"group_id": 309,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 74,
|
||||||
|
"group_id": 308,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 75,
|
||||||
|
"group_id": 308,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 76,
|
||||||
|
"group_id": 308,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 67,
|
||||||
|
"group_id": 307,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 68,
|
||||||
|
"group_id": 307,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 69,
|
||||||
|
"group_id": 307,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 64,
|
||||||
|
"group_id": 306,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 65,
|
||||||
|
"group_id": 306,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 66,
|
||||||
|
"group_id": 306,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 61,
|
||||||
|
"group_id": 305,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 62,
|
||||||
|
"group_id": 305,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63,
|
||||||
|
"group_id": 305,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 46,
|
||||||
|
"group_id": 304,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 47,
|
||||||
|
"group_id": 304,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 48,
|
||||||
|
"group_id": 304,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 43,
|
||||||
|
"group_id": 303,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 44,
|
||||||
|
"group_id": 303,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 45,
|
||||||
|
"group_id": 303,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 40,
|
||||||
|
"group_id": 302,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 41,
|
||||||
|
"group_id": 302,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 42,
|
||||||
|
"group_id": 302,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 37,
|
||||||
|
"group_id": 301,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 38,
|
||||||
|
"group_id": 301,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 39,
|
||||||
|
"group_id": 301,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 87,
|
||||||
|
"group_id": 9,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 88,
|
||||||
|
"group_id": 9,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 89,
|
||||||
|
"group_id": 9,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 90,
|
||||||
|
"group_id": 9,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 80,
|
||||||
|
"group_id": 8,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 81,
|
||||||
|
"group_id": 8,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 82,
|
||||||
|
"group_id": 8,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 83,
|
||||||
|
"group_id": 8,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 70,
|
||||||
|
"group_id": 7,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 71,
|
||||||
|
"group_id": 7,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 72,
|
||||||
|
"group_id": 7,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 73,
|
||||||
|
"group_id": 7,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 52,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 53,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 54,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 56,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 58,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 60,
|
||||||
|
"group_id": 6,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49,
|
||||||
|
"group_id": 5,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 50,
|
||||||
|
"group_id": 5,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 51,
|
||||||
|
"group_id": 5,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 29,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 30,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 31,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 33,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 34,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 35,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 36,
|
||||||
|
"group_id": 4,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 27,
|
||||||
|
"group_id": 3,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": "Puzzle_Unlock_Condition_0001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": "Puzzle_Unlock_Condition_0001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"group_id": 2,
|
||||||
|
"puzzle_difficulty": 3,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": "Puzzle_Unlock_Condition_0001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 0,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 1,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"group_id": 1,
|
||||||
|
"puzzle_difficulty": 2,
|
||||||
|
"is_additional": false,
|
||||||
|
"is_playable": true,
|
||||||
|
"release_condition_text_id": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
164
SVSim.Bootstrap/Data/seeds/reprinted-cards.json
Normal file
164
SVSim.Bootstrap/Data/seeds/reprinted-cards.json
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"card_id": 100114010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100211010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100214010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100214020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100314010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100314020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100314030
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100314040
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100314070
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100414010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100514010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100614010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100614020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100714010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100714020
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 100814010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101114010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105312010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106114010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107322010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111124010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111214010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111314010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111434010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111514010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111634010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111734010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111814010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112122010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112222010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112224010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112322010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112414010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112422010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112522010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112622010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112722010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112822010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112834010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113034010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113114010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113224010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113614010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113733010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 113824010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 114014010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 114031010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 114234010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 114834010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 115124010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 115214010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 115414010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 115814010
|
||||||
|
}
|
||||||
|
]
|
||||||
14
SVSim.Bootstrap/Data/seeds/rotation-config.json
Normal file
14
SVSim.Bootstrap/Data/seeds/rotation-config.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"ts_rotation_id": "10015",
|
||||||
|
"is_battle_pass_period": true,
|
||||||
|
"is_beginner_mission": false,
|
||||||
|
"card_set_id_for_resource_dl_view": 1,
|
||||||
|
"rotation_card_set_ids": [
|
||||||
|
10000,
|
||||||
|
10011,
|
||||||
|
10012,
|
||||||
|
10013,
|
||||||
|
10014,
|
||||||
|
10015
|
||||||
|
]
|
||||||
|
}
|
||||||
21
SVSim.Bootstrap/Data/seeds/sealed-season.json
Normal file
21
SVSim.Bootstrap/Data/seeds/sealed-season.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"enable": 1,
|
||||||
|
"crystal_cost": 600,
|
||||||
|
"rupy_cost": 600,
|
||||||
|
"ticket_cost": 4,
|
||||||
|
"deck_using_num_min": 30,
|
||||||
|
"schedule_id": 21,
|
||||||
|
"is_join": false,
|
||||||
|
"is_deck_code_maintenance": false,
|
||||||
|
"pack_info": [
|
||||||
|
10032,
|
||||||
|
10032,
|
||||||
|
10031,
|
||||||
|
10030,
|
||||||
|
10029
|
||||||
|
],
|
||||||
|
"sales_period_info": {
|
||||||
|
"sales_period_series": 33
|
||||||
|
}
|
||||||
|
}
|
||||||
7
SVSim.Bootstrap/Data/seeds/special-deck-formats.json
Normal file
7
SVSim.Bootstrap/Data/seeds/special-deck-formats.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"deck_format": "5",
|
||||||
|
"end_time": "2030-06-26 19:59:59"
|
||||||
|
}
|
||||||
|
]
|
||||||
958
SVSim.Bootstrap/Data/seeds/spot-cards.json
Normal file
958
SVSim.Bootstrap/Data/seeds/spot-cards.json
Normal file
@@ -0,0 +1,958 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"card_id": 101041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101041030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 101741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102442010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 102743010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 103741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 104741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 105741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 106741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107841030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108044010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 108841030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109841030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 110841030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 111843010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112041010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112041020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112141010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112141020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112141030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112241010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112241020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112241030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112341010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112341020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112341030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112441010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112441020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112441030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112541010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112541020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112541030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112641010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112641020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112641030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112741010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112741020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112741030,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112841010,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112841020,
|
||||||
|
"cost": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 112841030,
|
||||||
|
"cost": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
14
SVSim.Bootstrap/Data/seeds/unlimited-restrictions.json
Normal file
14
SVSim.Bootstrap/Data/seeds/unlimited-restrictions.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"card_id": 112834010,
|
||||||
|
"restriction_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 109623010,
|
||||||
|
"restriction_value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"card_id": 107813030,
|
||||||
|
"restriction_value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"data_headers": { "sid": "fixture", "short_udid": 1, "viewer_id": 1, "servertime": 1779591187, "result_code": 1 },
|
|
||||||
"data": {
|
|
||||||
"pack_config_list": [
|
|
||||||
{
|
|
||||||
"parent_gacha_id": 10001, "base_pack_id": 10001, "override_draw_effect_pack_id": 10001,
|
|
||||||
"override_ui_effect_pack_id": 10001, "gacha_type": 1, "sleeve_id": 3000011, "special_sleeve_id": 0,
|
|
||||||
"commence_date": "2015-04-01 00:00:00", "complete_date": "2030-12-31 23:59:59",
|
|
||||||
"cardpack_banner_list": [], "gacha_detail": "A pack contains 8 cards, including at least one silver, gold, or legendary card.",
|
|
||||||
"child_gacha_info": [
|
|
||||||
{ "gacha_id": 100002, "type_detail": 2, "cost": 100, "count": 8, "override_increase_gacha_point": "1" },
|
|
||||||
{ "gacha_id": 200001, "type_detail": 3, "cost": 50, "count": 8, "override_increase_gacha_point": "1", "is_daily_single": true },
|
|
||||||
{ "gacha_id": 400002, "type_detail": 7, "cost": 100, "count": 8, "override_increase_gacha_point": "1" }
|
|
||||||
],
|
|
||||||
"open_count": 0, "open_count_limit": 0, "is_hide": 0, "pack_category": 0,
|
|
||||||
"gacha_point": { "pack_id": "10001", "gacha_point": 0, "increase_gacha_point": "1", "exchangeable_gacha_point": 400, "is_exchangeable_gacha_point": false },
|
|
||||||
"is_pre_release": false, "exists_purchase_reward": false, "is_new": false, "sales_period_info": [], "poster_type": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parent_gacha_id": 92001, "base_pack_id": 90001, "override_draw_effect_pack_id": 90001,
|
|
||||||
"override_ui_effect_pack_id": 90001, "gacha_type": 1, "sleeve_id": 5090001, "special_sleeve_id": 0,
|
|
||||||
"commence_date": "2017-06-14 10:00:00", "complete_date": "2030-12-31 23:59:59",
|
|
||||||
"cardpack_banner_list": [], "gacha_detail": "A pack contains 8 cards, including at least one leader card!",
|
|
||||||
"child_gacha_info": [
|
|
||||||
{ "gacha_id": 920002, "type_detail": 5, "cost": 1, "count": 8, "item_id": "92001", "item_number": 0 }
|
|
||||||
],
|
|
||||||
"open_count": 0, "open_count_limit": 0, "is_hide": 1, "pack_category": 1, "gacha_point": null,
|
|
||||||
"is_pre_release": false, "exists_purchase_reward": false, "is_new": false, "sales_period_info": [], "poster_type": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parent_gacha_id": 16015, "base_pack_id": 10015, "override_draw_effect_pack_id": 10015,
|
|
||||||
"override_ui_effect_pack_id": 10015, "gacha_type": 1, "sleeve_id": 5010015, "special_sleeve_id": 0,
|
|
||||||
"commence_date": "2017-07-01 03:00:00", "complete_date": "2030-12-31 23:59:59",
|
|
||||||
"cardpack_banner_list": [
|
|
||||||
{ "banner_name": "card_pack_711331010_dialog", "dialog_title": "Dia_BuyCard_005_Title" }
|
|
||||||
],
|
|
||||||
"gacha_detail": "A pack contains 8 cards, including at least one silver, gold, or legendary card.",
|
|
||||||
"child_gacha_info": [
|
|
||||||
{ "gacha_id": 160152, "type_detail": 2, "cost": 100, "count": 8, "override_increase_gacha_point": "1" },
|
|
||||||
{ "gacha_id": 460152, "type_detail": 7, "cost": 100, "count": 8, "override_increase_gacha_point": "1" }
|
|
||||||
],
|
|
||||||
"open_count": 0, "open_count_limit": 0, "is_hide": 0, "pack_category": 0,
|
|
||||||
"gacha_point": { "pack_id": "10015", "gacha_point": 0, "increase_gacha_point": "1", "exchangeable_gacha_point": 400, "is_exchangeable_gacha_point": false },
|
|
||||||
"is_pre_release": false, "exists_purchase_reward": false, "is_new": false, "sales_period_info": [], "poster_type": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
154
SVSim.Bootstrap/Data/test-fixtures/seeds/packs.json
Normal file
154
SVSim.Bootstrap/Data/test-fixtures/seeds/packs.json
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"parent_gacha_id": 10001,
|
||||||
|
"base_pack_id": 10001,
|
||||||
|
"gacha_type": 1,
|
||||||
|
"pack_category": 0,
|
||||||
|
"poster_type": 0,
|
||||||
|
"commence_date": "2015-04-01 00:00:00",
|
||||||
|
"complete_date": "2030-12-31 23:59:59",
|
||||||
|
"sleeve_id": 3000011,
|
||||||
|
"special_sleeve_id": 0,
|
||||||
|
"override_draw_effect_pack_id": 10001,
|
||||||
|
"override_ui_effect_pack_id": 10001,
|
||||||
|
"gacha_detail": "A pack contains 8 cards, including at least one silver, gold, or legendary card.",
|
||||||
|
"is_hide": false,
|
||||||
|
"is_new": false,
|
||||||
|
"is_pre_release": false,
|
||||||
|
"open_count_limit": 0,
|
||||||
|
"sales_period_time": null,
|
||||||
|
"gacha_point": {
|
||||||
|
"exchangeable_point": 400,
|
||||||
|
"increase_gacha_point": 1
|
||||||
|
},
|
||||||
|
"child_gachas": [
|
||||||
|
{
|
||||||
|
"gacha_id": 100002,
|
||||||
|
"type_detail": 2,
|
||||||
|
"cost": 100,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": null,
|
||||||
|
"is_daily_single": false,
|
||||||
|
"override_increase_gacha_point": 1,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gacha_id": 200001,
|
||||||
|
"type_detail": 3,
|
||||||
|
"cost": 50,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": null,
|
||||||
|
"is_daily_single": true,
|
||||||
|
"override_increase_gacha_point": 1,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gacha_id": 400002,
|
||||||
|
"type_detail": 7,
|
||||||
|
"cost": 100,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": null,
|
||||||
|
"is_daily_single": false,
|
||||||
|
"override_increase_gacha_point": 1,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"banners": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parent_gacha_id": 92001,
|
||||||
|
"base_pack_id": 90001,
|
||||||
|
"gacha_type": 1,
|
||||||
|
"pack_category": 1,
|
||||||
|
"poster_type": 0,
|
||||||
|
"commence_date": "2017-06-14 10:00:00",
|
||||||
|
"complete_date": "2030-12-31 23:59:59",
|
||||||
|
"sleeve_id": 5090001,
|
||||||
|
"special_sleeve_id": 0,
|
||||||
|
"override_draw_effect_pack_id": 90001,
|
||||||
|
"override_ui_effect_pack_id": 90001,
|
||||||
|
"gacha_detail": "A pack contains 8 cards, including at least one leader card!",
|
||||||
|
"is_hide": true,
|
||||||
|
"is_new": false,
|
||||||
|
"is_pre_release": false,
|
||||||
|
"open_count_limit": 0,
|
||||||
|
"sales_period_time": null,
|
||||||
|
"gacha_point": null,
|
||||||
|
"child_gachas": [
|
||||||
|
{
|
||||||
|
"gacha_id": 920002,
|
||||||
|
"type_detail": 5,
|
||||||
|
"cost": 1,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": 92001,
|
||||||
|
"is_daily_single": false,
|
||||||
|
"override_increase_gacha_point": 0,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"banners": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parent_gacha_id": 16015,
|
||||||
|
"base_pack_id": 10015,
|
||||||
|
"gacha_type": 1,
|
||||||
|
"pack_category": 0,
|
||||||
|
"poster_type": 0,
|
||||||
|
"commence_date": "2017-07-01 03:00:00",
|
||||||
|
"complete_date": "2030-12-31 23:59:59",
|
||||||
|
"sleeve_id": 5010015,
|
||||||
|
"special_sleeve_id": 0,
|
||||||
|
"override_draw_effect_pack_id": 10015,
|
||||||
|
"override_ui_effect_pack_id": 10015,
|
||||||
|
"gacha_detail": "A pack contains 8 cards, including at least one silver, gold, or legendary card.",
|
||||||
|
"is_hide": false,
|
||||||
|
"is_new": false,
|
||||||
|
"is_pre_release": false,
|
||||||
|
"open_count_limit": 0,
|
||||||
|
"sales_period_time": null,
|
||||||
|
"gacha_point": {
|
||||||
|
"exchangeable_point": 400,
|
||||||
|
"increase_gacha_point": 1
|
||||||
|
},
|
||||||
|
"child_gachas": [
|
||||||
|
{
|
||||||
|
"gacha_id": 160152,
|
||||||
|
"type_detail": 2,
|
||||||
|
"cost": 100,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": null,
|
||||||
|
"is_daily_single": false,
|
||||||
|
"override_increase_gacha_point": 1,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gacha_id": 460152,
|
||||||
|
"type_detail": 7,
|
||||||
|
"cost": 100,
|
||||||
|
"card_count": 8,
|
||||||
|
"item_id": null,
|
||||||
|
"is_daily_single": false,
|
||||||
|
"override_increase_gacha_point": 1,
|
||||||
|
"purchase_limit_count": 0,
|
||||||
|
"free_gacha_campaign_id": null,
|
||||||
|
"campaign_name": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"banners": [
|
||||||
|
{
|
||||||
|
"banner_name": "card_pack_711331010_dialog",
|
||||||
|
"dialog_title": "Dia_BuyCard_005_Title"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
37
SVSim.Bootstrap/Importers/ArenaSeasonImporter.cs
Normal file
37
SVSim.Bootstrap/Importers/ArenaSeasonImporter.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton upsert (Id=1) of the active Take Two arena season config from
|
||||||
|
/// <c>seeds/arena-season.json</c>. <c>format_info</c> is preserved verbatim as a jsonb blob.
|
||||||
|
/// </summary>
|
||||||
|
public class ArenaSeasonImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var s = SeedLoader.LoadObject<ArenaSeasonSeed>(Path.Combine(seedDir, "arena-season.json"));
|
||||||
|
if (s is null) return 0;
|
||||||
|
|
||||||
|
var existing = await context.ArenaSeasons.FirstOrDefaultAsync(e => e.Id == 1);
|
||||||
|
var entry = existing ?? new ArenaSeasonConfig { Id = 1 };
|
||||||
|
entry.Mode = s.Mode;
|
||||||
|
entry.Enable = s.Enable;
|
||||||
|
entry.Cost = s.Cost;
|
||||||
|
entry.RupyCost = s.RupyCost;
|
||||||
|
entry.TicketCost = s.TicketCost;
|
||||||
|
entry.IsJoin = s.IsJoin;
|
||||||
|
entry.FormatInfo = s.FormatInfo.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}"
|
||||||
|
: JsonSerializer.Serialize(s.FormatInfo);
|
||||||
|
if (existing is null) context.ArenaSeasons.Add(entry);
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[ArenaSeasonImporter] {(existing is null ? "+1" : "~1")}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
SVSim.Bootstrap/Importers/AvatarAbilityImporter.cs
Normal file
41
SVSim.Bootstrap/Importers/AvatarAbilityImporter.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of Avatar (Hero) ability rows from <c>seeds/avatar-abilities.json</c>.
|
||||||
|
/// Keyed by leader_skin_id. Ability / passive-ability DSL strings are preserved verbatim.
|
||||||
|
/// </summary>
|
||||||
|
public class AvatarAbilityImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<AvatarAbilitySeed>(Path.Combine(seedDir, "avatar-abilities.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
|
||||||
|
var existing = await context.AvatarAbilities.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex) ? ex : new AvatarAbilityEntry { Id = s.Id };
|
||||||
|
entry.BattleStartFirstPlayerTurnBp = s.BattleStartFirstPlayerTurnBp;
|
||||||
|
entry.BattleStartSecondPlayerTurnBp = s.BattleStartSecondPlayerTurnBp;
|
||||||
|
entry.BattleStartMaxLife = s.BattleStartMaxLife;
|
||||||
|
entry.AbilityCost = s.AbilityCost;
|
||||||
|
entry.Ability = s.Ability;
|
||||||
|
entry.PassiveAbility = s.PassiveAbility;
|
||||||
|
entry.AbilityDesc = s.AbilityDesc;
|
||||||
|
entry.PassiveAbilityDesc = s.PassiveAbilityDesc;
|
||||||
|
if (ex is null) { context.AvatarAbilities.Add(entry); existing[s.Id] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[AvatarAbilityImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
SVSim.Bootstrap/Importers/BattlePassImporter.cs
Normal file
38
SVSim.Bootstrap/Importers/BattlePassImporter.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of battle-pass level rows from <c>seeds/battle-pass-levels.json</c>.
|
||||||
|
/// Curve is global; rows missing from the seed are LEFT INTACT.
|
||||||
|
/// </summary>
|
||||||
|
public class BattlePassImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<BattlePassLevelSeed>(Path.Combine(seedDir, "battle-pass-levels.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[BattlePassImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.BattlePassLevels.ToDictionaryAsync(e => e.Level);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Level == 0) continue;
|
||||||
|
var entry = existing.TryGetValue(s.Level, out var ex) ? ex : new BattlePassLevelEntry { Level = s.Level };
|
||||||
|
entry.RequiredPoint = s.RequiredPoint;
|
||||||
|
if (ex is null) { context.BattlePassLevels.Add(entry); existing[s.Level] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[BattlePassImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
90
SVSim.Bootstrap/Importers/BattlePassRewardImporter.cs
Normal file
90
SVSim.Bootstrap/Importers/BattlePassRewardImporter.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Enums;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Authoritative upsert of battle-pass rewards from <c>seeds/battle-pass-rewards.json</c>.
|
||||||
|
/// For each (season_id, track, level) row in the seed: upsert. For rows in the DB that match
|
||||||
|
/// a seed-mentioned season but are NOT in the seed: DELETE (seed is authoritative per season).
|
||||||
|
/// Rewards for seasons not mentioned in the seed are left untouched.
|
||||||
|
/// </summary>
|
||||||
|
public class BattlePassRewardImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<BattlePassRewardSeed>(Path.Combine(seedDir, "battle-pass-rewards.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[BattlePassRewardImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var seededSeasonIds = seed.Select(s => s.SeasonId).Distinct().ToHashSet();
|
||||||
|
var dbRows = await context.BattlePassRewards
|
||||||
|
.Where(r => seededSeasonIds.Contains(r.SeasonId))
|
||||||
|
.ToListAsync();
|
||||||
|
var dbByKey = dbRows.ToDictionary(r => (r.SeasonId, r.Track, r.Level));
|
||||||
|
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
var seenKeys = new HashSet<(int, BattlePassTrack, int)>();
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
var track = ParseTrack(s.Track);
|
||||||
|
var key = (s.SeasonId, track, s.Level);
|
||||||
|
seenKeys.Add(key);
|
||||||
|
if (dbByKey.TryGetValue(key, out var ex))
|
||||||
|
{
|
||||||
|
ex.RewardType = s.RewardType;
|
||||||
|
ex.RewardDetailId = s.RewardDetailId;
|
||||||
|
ex.RewardNumber = s.RewardNumber;
|
||||||
|
ex.IsAppealExclusion = s.IsAppealExclusion;
|
||||||
|
updated++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.BattlePassRewards.Add(new BattlePassRewardEntry
|
||||||
|
{
|
||||||
|
Id = MakeId(s.SeasonId, track, s.Level),
|
||||||
|
SeasonId = s.SeasonId, Track = track, Level = s.Level,
|
||||||
|
RewardType = s.RewardType, RewardDetailId = s.RewardDetailId,
|
||||||
|
RewardNumber = s.RewardNumber, IsAppealExclusion = s.IsAppealExclusion,
|
||||||
|
});
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authoritative deletion within seeded seasons.
|
||||||
|
int deleted = 0;
|
||||||
|
foreach (var row in dbRows)
|
||||||
|
{
|
||||||
|
if (!seenKeys.Contains((row.SeasonId, row.Track, row.Level)))
|
||||||
|
{
|
||||||
|
context.BattlePassRewards.Remove(row);
|
||||||
|
deleted++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[BattlePassRewardImporter] +{created}/~{updated}/-{deleted}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BattlePassTrack ParseTrack(string s) => s.ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"normal" => BattlePassTrack.Normal,
|
||||||
|
"premium" => BattlePassTrack.Premium,
|
||||||
|
_ => throw new InvalidOperationException($"unknown battle pass track: {s}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Derives a stable surrogate PK from the (SeasonId, Track, Level) natural key.
|
||||||
|
/// Encoding: season * 10_000 + track * 1_000 + level.
|
||||||
|
/// Safe for season < 10_000, track ∈ {0,1}, level < 1_000 — all realistic values.
|
||||||
|
/// </summary>
|
||||||
|
private static long MakeId(int seasonId, BattlePassTrack track, int level) =>
|
||||||
|
(long)seasonId * 10_000L + (int)track * 1_000 + level;
|
||||||
|
}
|
||||||
48
SVSim.Bootstrap/Importers/BattlePassSeasonImporter.cs
Normal file
48
SVSim.Bootstrap/Importers/BattlePassSeasonImporter.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of battle-pass seasons from <c>seeds/battle-pass-seasons.json</c>.
|
||||||
|
/// Rows missing from the seed are LEFT INTACT (historic seasons).
|
||||||
|
/// </summary>
|
||||||
|
public class BattlePassSeasonImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<BattlePassSeasonSeed>(Path.Combine(seedDir, "battle-pass-seasons.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[BattlePassSeasonImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.BattlePassSeasons.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex) ? ex : new BattlePassSeasonEntry { Id = s.Id };
|
||||||
|
entry.Name = s.Name;
|
||||||
|
entry.MaxLevel = s.MaxLevel;
|
||||||
|
// Postgres 'timestamp with time zone' only accepts UTC offset; JST-offset values
|
||||||
|
// from the seed are converted to UTC to preserve the instant. Comparisons via
|
||||||
|
// DateTimeOffset are instant-based, so the JST→UTC conversion is semantically lossless.
|
||||||
|
entry.StartDate = DateTimeOffset.Parse(s.StartDate, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime();
|
||||||
|
entry.EndDate = DateTimeOffset.Parse(s.EndDate, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUniversalTime();
|
||||||
|
entry.CanPurchase = s.CanPurchase;
|
||||||
|
entry.PriceCrystal = s.PriceCrystal;
|
||||||
|
entry.Description = s.Description;
|
||||||
|
if (ex is null) { context.BattlePassSeasons.Add(entry); existing[s.Id] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[BattlePassSeasonImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
using SVSim.Database;
|
using SVSim.Database;
|
||||||
using SVSim.Database.Models;
|
using SVSim.Database.Models;
|
||||||
using static SVSim.Bootstrap.Importers.ImporterBase;
|
|
||||||
|
|
||||||
namespace SVSim.Bootstrap.Importers;
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads the prebuilt-deck catalog from a mix of client-master CSVs and one prod-capture JSON.
|
/// Loads the prebuilt-deck catalog from a mix of client-master CSVs and one seed JSON.
|
||||||
/// Three methods run in dependency order (see Bootstrap/Program.cs):
|
/// Three methods run in dependency order (see Bootstrap/Program.cs):
|
||||||
/// 1. ImportSeriesAsync — build_deck_series_master.csv → 22 series rows (all IsEnabled=false initially)
|
/// 1. ImportSeriesAsync — build_deck_series_master.csv → 22 series rows (all IsEnabled=false initially)
|
||||||
/// 2. ImportCatalogAsync — prod-captures/build_deck-info-*.json → enriches 7 series + 53 products (Task 15)
|
/// 2. ImportCatalogAsync — seeds/build-deck-catalog.json → enriches 7 series + 53 products
|
||||||
|
/// (tier backfill for missing intro/regular prices is performed by the extractor)
|
||||||
/// 3. ImportPackageAsync — build_deck_package_master.csv → card lists for all 112 products,
|
/// 3. ImportPackageAsync — build_deck_package_master.csv → card lists for all 112 products,
|
||||||
/// creates disabled stubs for products not seeded by the catalog importer
|
/// creates disabled stubs for products not seeded by the catalog importer
|
||||||
/// Idempotent — re-runnable on the same files.
|
/// Idempotent — re-runnable on the same files.
|
||||||
@@ -133,14 +133,13 @@ public class BuildDeckImporter
|
|||||||
return created + updated;
|
return created + updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> ImportCatalogAsync(SVSimDbContext db, string capturesDir)
|
public async Task<int> ImportCatalogAsync(SVSimDbContext db, string seedDir)
|
||||||
{
|
{
|
||||||
var data = LoadCapture(capturesDir, "build_deck-info");
|
var seed = SeedLoader.LoadList<BuildDeckCatalogSeed>(Path.Combine(seedDir, "build-deck-catalog.json"));
|
||||||
if (data is null) return 0;
|
if (seed.Count == 0) return 0;
|
||||||
|
|
||||||
int touchedSeries = 0, touchedProducts = 0;
|
int touchedSeries = 0, touchedProducts = 0;
|
||||||
|
|
||||||
// Load existing rows for fast lookup
|
|
||||||
var existingSeries = await db.BuildDeckSeries
|
var existingSeries = await db.BuildDeckSeries
|
||||||
.Include(s => s.SeriesRewards)
|
.Include(s => s.SeriesRewards)
|
||||||
.ToDictionaryAsync(s => s.Id);
|
.ToDictionaryAsync(s => s.Id);
|
||||||
@@ -148,126 +147,75 @@ public class BuildDeckImporter
|
|||||||
.Include(p => p.Rewards)
|
.Include(p => p.Rewards)
|
||||||
.ToDictionaryAsync(p => p.Id);
|
.ToDictionaryAsync(p => p.Id);
|
||||||
|
|
||||||
// The captured data root is an object keyed by order_id string ("15"…"21"); iterate values.
|
foreach (var s in seed)
|
||||||
foreach (var seriesNode in data.Value.EnumerateObject())
|
|
||||||
{
|
{
|
||||||
var s = seriesNode.Value;
|
if (s.SeriesId == 0) continue;
|
||||||
int seriesId = GetInt(s, "series_id");
|
|
||||||
int orderId = GetInt(s, "order_id");
|
|
||||||
bool isNew = GetBool(s, "is_new");
|
|
||||||
|
|
||||||
if (!existingSeries.TryGetValue(seriesId, out var seriesRow))
|
if (!existingSeries.TryGetValue(s.SeriesId, out var seriesRow))
|
||||||
{
|
{
|
||||||
// Catalog runs before package importer in production, so series rows from the series
|
// Catalog typically runs after the series CSV; if a seed series isn't in the
|
||||||
// CSV should already exist. If not (e.g. the capture has a series the CSV doesn't),
|
// CSV we create a bare stub so the FK from products holds.
|
||||||
// create a bare row so the FK from products holds.
|
|
||||||
seriesRow = new BuildDeckSeriesEntry
|
seriesRow = new BuildDeckSeriesEntry
|
||||||
{
|
{
|
||||||
Id = seriesId, NameKey = string.Empty, IntroKey = string.Empty,
|
Id = s.SeriesId, NameKey = string.Empty, IntroKey = string.Empty,
|
||||||
TitlePath = string.Empty, DrumrollPath = string.Empty,
|
TitlePath = string.Empty, DrumrollPath = string.Empty,
|
||||||
};
|
};
|
||||||
db.BuildDeckSeries.Add(seriesRow);
|
db.BuildDeckSeries.Add(seriesRow);
|
||||||
existingSeries[seriesId] = seriesRow;
|
existingSeries[s.SeriesId] = seriesRow;
|
||||||
}
|
}
|
||||||
seriesRow.OrderIndex = orderId;
|
seriesRow.OrderIndex = s.OrderId;
|
||||||
seriesRow.IsNew = isNew;
|
seriesRow.IsNew = s.IsNew;
|
||||||
seriesRow.IsEnabled = true;
|
seriesRow.IsEnabled = true;
|
||||||
|
|
||||||
// Series rewards: replace wholesale (capture is authoritative for enabled series)
|
|
||||||
seriesRow.SeriesRewards.Clear();
|
seriesRow.SeriesRewards.Clear();
|
||||||
if (s.TryGetProperty("series_rewards", out var seriesRewards) &&
|
foreach (var r in s.SeriesRewards)
|
||||||
seriesRewards.ValueKind == JsonValueKind.Object)
|
|
||||||
{
|
{
|
||||||
foreach (var tier in seriesRewards.EnumerateObject())
|
seriesRow.SeriesRewards.Add(new BuildDeckSeriesRewardEntry
|
||||||
{
|
{
|
||||||
if (!int.TryParse(tier.Name, out int tierIndex)) continue;
|
TierIndex = r.TierIndex,
|
||||||
if (!tier.Value.TryGetProperty("reward_list", out var rewardList) ||
|
ItemIndex = r.ItemIndex,
|
||||||
rewardList.ValueKind != JsonValueKind.Array) continue;
|
RewardType = r.RewardType,
|
||||||
|
RewardDetailId = r.RewardDetailId,
|
||||||
int itemIndex = 0;
|
RewardNumber = r.RewardNumber,
|
||||||
foreach (var r in rewardList.EnumerateArray())
|
MessageId = r.MessageId,
|
||||||
{
|
});
|
||||||
seriesRow.SeriesRewards.Add(new BuildDeckSeriesRewardEntry
|
|
||||||
{
|
|
||||||
TierIndex = tierIndex,
|
|
||||||
ItemIndex = itemIndex++,
|
|
||||||
RewardType = GetInt(r, "reward_type"),
|
|
||||||
RewardDetailId = GetLong(r, "reward_detail_id"),
|
|
||||||
RewardNumber = GetInt(r, "reward_number"),
|
|
||||||
MessageId = GetInt(r, "message_id"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
touchedSeries++;
|
touchedSeries++;
|
||||||
|
|
||||||
// Products
|
foreach (var p in s.Products)
|
||||||
if (!s.TryGetProperty("products", out var products) || products.ValueKind != JsonValueKind.Array)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// First pass: parse each captured product, track intro/regular tiers per product.
|
|
||||||
var capturedThisSeries = new List<BuildDeckProductEntry>();
|
|
||||||
foreach (var p in products.EnumerateArray())
|
|
||||||
{
|
{
|
||||||
int productId = GetInt(p, "product_id");
|
if (!existingProducts.TryGetValue(p.ProductId, out var productRow))
|
||||||
|
|
||||||
if (!existingProducts.TryGetValue(productId, out var productRow))
|
|
||||||
{
|
{
|
||||||
productRow = new BuildDeckProductEntry { Id = productId, SeriesId = seriesId };
|
productRow = new BuildDeckProductEntry { Id = p.ProductId, SeriesId = s.SeriesId };
|
||||||
db.BuildDeckProducts.Add(productRow);
|
db.BuildDeckProducts.Add(productRow);
|
||||||
existingProducts[productId] = productRow;
|
existingProducts[p.ProductId] = productRow;
|
||||||
}
|
}
|
||||||
productRow.SeriesId = seriesId;
|
productRow.SeriesId = s.SeriesId;
|
||||||
productRow.LeaderId = GetInt(p, "leader_id");
|
productRow.LeaderId = p.LeaderId;
|
||||||
productRow.DeckCode = GetString(p, "deck_code");
|
productRow.DeckCode = p.DeckCode;
|
||||||
productRow.ProductNameKey = GetString(p, "product_name");
|
productRow.ProductNameKey = p.ProductName;
|
||||||
productRow.FeaturedCardId = GetLong(p, "featured_card_id");
|
productRow.FeaturedCardId = p.FeaturedCardId;
|
||||||
productRow.PurchaseNumMax = GetInt(p, "purchase_num_max");
|
productRow.PurchaseNumMax = p.PurchaseNumMax;
|
||||||
productRow.IsEnabled = true;
|
productRow.IsEnabled = true;
|
||||||
|
productRow.IntroPriceCrystal = p.IntroPriceCrystal;
|
||||||
|
productRow.RegularPriceCrystal = p.RegularPriceCrystal;
|
||||||
|
productRow.IntroPriceRupy = p.IntroPriceRupy;
|
||||||
|
productRow.RegularPriceRupy = p.RegularPriceRupy;
|
||||||
|
|
||||||
bool isFirstPrice = GetBool(p, "is_first_price");
|
|
||||||
|
|
||||||
// Tier-aware price ingestion: each captured row has ONE price tier (intro OR regular).
|
|
||||||
int? priceCrystal = p.TryGetProperty("price_crystal", out var pc) && pc.ValueKind != JsonValueKind.Null
|
|
||||||
? (int?)GetInt(p, "price_crystal") : null;
|
|
||||||
int? priceRupy = p.TryGetProperty("price_rupy", out var pr) && pr.ValueKind != JsonValueKind.Null
|
|
||||||
? (int?)GetInt(p, "price_rupy") : null;
|
|
||||||
|
|
||||||
if (priceCrystal is not null)
|
|
||||||
{
|
|
||||||
if (isFirstPrice) productRow.IntroPriceCrystal = priceCrystal;
|
|
||||||
else productRow.RegularPriceCrystal = priceCrystal;
|
|
||||||
}
|
|
||||||
if (priceRupy is not null)
|
|
||||||
{
|
|
||||||
if (isFirstPrice) productRow.IntroPriceRupy = priceRupy;
|
|
||||||
else productRow.RegularPriceRupy = priceRupy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Product rewards: replace wholesale
|
|
||||||
productRow.Rewards.Clear();
|
productRow.Rewards.Clear();
|
||||||
if (p.TryGetProperty("rewards", out var rewards) && rewards.ValueKind == JsonValueKind.Object)
|
foreach (var r in p.Rewards)
|
||||||
{
|
{
|
||||||
foreach (var r in rewards.EnumerateObject())
|
productRow.Rewards.Add(new BuildDeckProductRewardEntry
|
||||||
{
|
{
|
||||||
if (!int.TryParse(r.Name, out int idx)) continue;
|
RewardIndex = r.RewardIndex,
|
||||||
productRow.Rewards.Add(new BuildDeckProductRewardEntry
|
RewardType = r.RewardType,
|
||||||
{
|
RewardDetailId = r.RewardDetailId,
|
||||||
RewardIndex = idx,
|
RewardNumber = r.RewardNumber,
|
||||||
RewardType = GetInt(r.Value, "reward_type"),
|
MessageId = r.MessageId,
|
||||||
RewardDetailId = GetLong(r.Value, "reward_detail_id"),
|
});
|
||||||
RewardNumber = GetInt(r.Value, "reward_number"),
|
|
||||||
MessageId = GetInt(r.Value, "message_id"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
capturedThisSeries.Add(productRow);
|
|
||||||
touchedProducts++;
|
touchedProducts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second pass: backfill missing tier per-series when sibling products share a unique value.
|
|
||||||
BackfillSeriesTier(capturedThisSeries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
@@ -275,63 +223,6 @@ public class BuildDeckImporter
|
|||||||
return touchedSeries + touchedProducts;
|
return touchedSeries + touchedProducts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BackfillSeriesTier(IReadOnlyList<BuildDeckProductEntry> productsInSeries)
|
|
||||||
{
|
|
||||||
// For each (Currency, Tier) pair, if all populated values across siblings are the same,
|
|
||||||
// propagate that value to products that are missing the corresponding tier.
|
|
||||||
BackfillIntroCrystal(productsInSeries);
|
|
||||||
BackfillRegularCrystal(productsInSeries);
|
|
||||||
BackfillIntroRupy(productsInSeries);
|
|
||||||
BackfillRegularRupy(productsInSeries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void BackfillIntroCrystal(IReadOnlyList<BuildDeckProductEntry> products)
|
|
||||||
{
|
|
||||||
var distinct = products.Where(p => p.IntroPriceCrystal.HasValue).Select(p => p.IntroPriceCrystal!.Value).Distinct().ToList();
|
|
||||||
if (distinct.Count != 1) return;
|
|
||||||
int value = distinct[0];
|
|
||||||
foreach (var p in products)
|
|
||||||
{
|
|
||||||
if (p.IntroPriceCrystal is null) p.IntroPriceCrystal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void BackfillRegularCrystal(IReadOnlyList<BuildDeckProductEntry> products)
|
|
||||||
{
|
|
||||||
var distinct = products.Where(p => p.RegularPriceCrystal.HasValue).Select(p => p.RegularPriceCrystal!.Value).Distinct().ToList();
|
|
||||||
if (distinct.Count != 1) return;
|
|
||||||
int value = distinct[0];
|
|
||||||
foreach (var p in products)
|
|
||||||
{
|
|
||||||
// For PurchaseNumMax == 1 products, never backfill the Regular tier — they have no second buy.
|
|
||||||
if (p.PurchaseNumMax <= 1) continue;
|
|
||||||
if (p.RegularPriceCrystal is null) p.RegularPriceCrystal = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void BackfillIntroRupy(IReadOnlyList<BuildDeckProductEntry> products)
|
|
||||||
{
|
|
||||||
var distinct = products.Where(p => p.IntroPriceRupy.HasValue).Select(p => p.IntroPriceRupy!.Value).Distinct().ToList();
|
|
||||||
if (distinct.Count != 1) return;
|
|
||||||
int value = distinct[0];
|
|
||||||
foreach (var p in products)
|
|
||||||
{
|
|
||||||
if (p.IntroPriceRupy is null) p.IntroPriceRupy = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void BackfillRegularRupy(IReadOnlyList<BuildDeckProductEntry> products)
|
|
||||||
{
|
|
||||||
var distinct = products.Where(p => p.RegularPriceRupy.HasValue).Select(p => p.RegularPriceRupy!.Value).Distinct().ToList();
|
|
||||||
if (distinct.Count != 1) return;
|
|
||||||
int value = distinct[0];
|
|
||||||
foreach (var p in products)
|
|
||||||
{
|
|
||||||
if (p.PurchaseNumMax <= 1) continue;
|
|
||||||
if (p.RegularPriceRupy is null) p.RegularPriceRupy = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps a product_id to its series_id using the numeric pattern derived from the /info capture
|
/// Maps a product_id to its series_id using the numeric pattern derived from the /info capture
|
||||||
/// and CSV inspection.
|
/// and CSV inspection.
|
||||||
|
|||||||
165
SVSim.Bootstrap/Importers/CardListsImporter.cs
Normal file
165
SVSim.Bootstrap/Importers/CardListsImporter.cs
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of the six card-id-keyed tables from load-index seeds:
|
||||||
|
/// SpotCards, ReprintedCards, UnlimitedRestrictions, LoadingExclusionCards,
|
||||||
|
/// MaintenanceCards, FeatureMaintenances. Loads the Cards FK set once for orphan warnings.
|
||||||
|
/// Rows missing from a seed are LEFT INTACT — a partial seed shouldn't silently delete entries.
|
||||||
|
/// FeatureMaintenances clears-and-rewrites because its synthetic ordinal Id has no natural-key semantics.
|
||||||
|
/// </summary>
|
||||||
|
public class CardListsImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var knownCards = new HashSet<long>(await context.Cards.Select(c => c.Id).ToListAsync());
|
||||||
|
int total = 0;
|
||||||
|
total += await ImportSpot(context, seedDir, knownCards);
|
||||||
|
total += await ImportReprinted(context, seedDir, knownCards);
|
||||||
|
total += await ImportUnlimited(context, seedDir, knownCards);
|
||||||
|
total += await ImportLoadingExclusion(context, seedDir, knownCards);
|
||||||
|
total += await ImportMaintenance(context, seedDir);
|
||||||
|
total += await ImportFeatureMaintenances(context, seedDir);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportSpot(SVSimDbContext context, string seedDir, HashSet<long> knownCards)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<SpotCardSeed>(Path.Combine(seedDir, "spot-cards.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
var existing = await context.SpotCards.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0, orphans = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.CardId == 0) continue;
|
||||||
|
if (!knownCards.Contains(s.CardId)) orphans++;
|
||||||
|
var entry = existing.TryGetValue(s.CardId, out var ex) ? ex : new SpotCardEntry { Id = s.CardId };
|
||||||
|
entry.Cost = s.Cost;
|
||||||
|
if (ex is null) { context.SpotCards.Add(entry); existing[s.CardId] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
WarnOrphans("SpotCards", orphans);
|
||||||
|
Console.WriteLine($"[CardListsImporter] SpotCards +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportReprinted(SVSimDbContext context, string seedDir, HashSet<long> knownCards)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<ReprintedCardSeed>(Path.Combine(seedDir, "reprinted-cards.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
var existing = await context.ReprintedCards.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, orphans = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.CardId == 0) continue;
|
||||||
|
if (!knownCards.Contains(s.CardId)) orphans++;
|
||||||
|
if (existing.ContainsKey(s.CardId)) continue;
|
||||||
|
var entry = new ReprintedCardEntry { Id = s.CardId };
|
||||||
|
context.ReprintedCards.Add(entry);
|
||||||
|
existing[s.CardId] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
WarnOrphans("ReprintedCards", orphans);
|
||||||
|
Console.WriteLine($"[CardListsImporter] ReprintedCards +{created}");
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportUnlimited(SVSimDbContext context, string seedDir, HashSet<long> knownCards)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<UnlimitedRestrictionSeed>(Path.Combine(seedDir, "unlimited-restrictions.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
var existing = await context.UnlimitedRestrictions.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0, orphans = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.CardId == 0) continue;
|
||||||
|
if (!knownCards.Contains(s.CardId)) orphans++;
|
||||||
|
var entry = existing.TryGetValue(s.CardId, out var ex) ? ex : new UnlimitedRestrictionEntry { Id = s.CardId };
|
||||||
|
entry.RestrictionValue = s.RestrictionValue;
|
||||||
|
if (ex is null) { context.UnlimitedRestrictions.Add(entry); existing[s.CardId] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
WarnOrphans("UnlimitedRestrictions", orphans);
|
||||||
|
Console.WriteLine($"[CardListsImporter] UnlimitedRestrictions +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportLoadingExclusion(SVSimDbContext context, string seedDir, HashSet<long> knownCards)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<LoadingExclusionCardSeed>(Path.Combine(seedDir, "loading-exclusion-cards.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
var existing = await context.LoadingExclusionCards.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, orphans = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.CardId == 0) continue;
|
||||||
|
if (!knownCards.Contains(s.CardId)) orphans++;
|
||||||
|
if (existing.ContainsKey(s.CardId)) continue;
|
||||||
|
var entry = new LoadingExclusionCardEntry { Id = s.CardId };
|
||||||
|
context.LoadingExclusionCards.Add(entry);
|
||||||
|
existing[s.CardId] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
WarnOrphans("LoadingExclusionCards", orphans);
|
||||||
|
Console.WriteLine($"[CardListsImporter] LoadingExclusionCards +{created}");
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportMaintenance(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<MaintenanceCardSeed>(Path.Combine(seedDir, "maintenance-cards.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
var existing = await context.MaintenanceCards.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.CardId == 0) continue;
|
||||||
|
if (existing.ContainsKey(s.CardId)) continue;
|
||||||
|
var entry = new MaintenanceCardEntry { Id = s.CardId };
|
||||||
|
context.MaintenanceCards.Add(entry);
|
||||||
|
existing[s.CardId] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
Console.WriteLine($"[CardListsImporter] MaintenanceCards +{created}");
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> ImportFeatureMaintenances(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<FeatureMaintenanceSeed>(Path.Combine(seedDir, "feature-maintenances.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
// FeatureMaintenances has a synthetic int Id assigned by the extractor (1-based ordinal).
|
||||||
|
// FeatureMaintenances use a synthetic ordinal id from the extractor; we clear-and-rewrite to
|
||||||
|
// keep re-runs idempotent and match "the latest seed is authoritative". Pre-existing rows
|
||||||
|
// with seed-absent ids are dropped here (acceptable: only synthetic ordinals, no FKs
|
||||||
|
// reference this table).
|
||||||
|
var existing = await context.FeatureMaintenances.ToListAsync();
|
||||||
|
context.FeatureMaintenances.RemoveRange(existing);
|
||||||
|
int created = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
context.FeatureMaintenances.Add(new FeatureMaintenanceEntry
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
FeatureKey = s.FeatureKey,
|
||||||
|
Data = s.Data.ValueKind == JsonValueKind.Undefined ? "{}" : JsonSerializer.Serialize(s.Data),
|
||||||
|
});
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
Console.WriteLine($"[CardListsImporter] FeatureMaintenances: -{existing.Count}/+{created}");
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WarnOrphans(string label, int count)
|
||||||
|
{
|
||||||
|
if (count > 0)
|
||||||
|
Console.Error.WriteLine($"[CardListsImporter] Warning: {label} has {count} orphan card_id(s) — run CardImporter first for clean references.");
|
||||||
|
}
|
||||||
|
}
|
||||||
37
SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs
Normal file
37
SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of daily-login-bonus campaign rows from <c>seeds/daily-login-bonus.json</c>.
|
||||||
|
/// <c>bonus_data</c> array preserved verbatim — prod observed empty arrays outside active events.
|
||||||
|
/// </summary>
|
||||||
|
public class DailyLoginBonusImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<DailyLoginBonusSeed>(Path.Combine(seedDir, "daily-login-bonus.json"));
|
||||||
|
if (seed.Count == 0) return 0;
|
||||||
|
|
||||||
|
var existing = await context.DailyLoginBonuses.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex) ? ex : new DailyLoginBonusEntry { Id = s.Id };
|
||||||
|
entry.BonusData = s.BonusData.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "[]"
|
||||||
|
: JsonSerializer.Serialize(s.BonusData);
|
||||||
|
if (ex is null) { context.DailyLoginBonuses.Add(entry); existing[s.Id] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[DailyLoginBonusImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
SVSim.Bootstrap/Importers/DefaultDeckImporter.cs
Normal file
60
SVSim.Bootstrap/Importers/DefaultDeckImporter.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of default decks from <c>seeds/default-decks.json</c>. Warns on orphan card
|
||||||
|
/// references (card_id not in Cards table) but never fails — CardImporter must run first for a
|
||||||
|
/// clean warning-free run. Rows missing from the seed are LEFT INTACT.
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultDeckImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<DefaultDeckSeed>(Path.Combine(seedDir, "default-decks.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[DefaultDeckImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.DefaultDecks.ToDictionaryAsync(e => e.Id);
|
||||||
|
var knownCards = new HashSet<long>(await context.Cards.Select(c => c.Id).ToListAsync());
|
||||||
|
int created = 0, updated = 0, orphans = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex) ? ex : new DefaultDeckEntry { Id = s.Id };
|
||||||
|
entry.ClassId = s.ClassId;
|
||||||
|
entry.SleeveId = s.SleeveId;
|
||||||
|
entry.LeaderSkinId = s.LeaderSkinId;
|
||||||
|
entry.DeckName = s.DeckName;
|
||||||
|
entry.CardIdArray = JsonSerializer.Serialize(s.CardIdArray);
|
||||||
|
|
||||||
|
// Orphan count against card master — informational, never throws.
|
||||||
|
foreach (var cardId in s.CardIdArray)
|
||||||
|
{
|
||||||
|
if (!knownCards.Contains(cardId)) orphans++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex is null) { context.DefaultDecks.Add(entry); existing[s.Id] = entry; created++; }
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
WarnOrphans("DefaultDecks.card_id_array", orphans);
|
||||||
|
Console.WriteLine($"[DefaultDeckImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WarnOrphans(string label, int count)
|
||||||
|
{
|
||||||
|
if (count > 0)
|
||||||
|
Console.Error.WriteLine($"[DefaultDeckImporter] Warning: {label} has {count} orphan card_id(s) — run CardImporter first for clean references.");
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,84 +1,13 @@
|
|||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace SVSim.Bootstrap.Importers;
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shared helpers for content importers. Loads a prod-capture JSON file by endpoint name from
|
/// Tiny shared helper for content importers. Capture parsing has moved out of the bootstrap
|
||||||
/// a captures directory, returning the inner <c>data</c> element. Picks the latest matching dated
|
/// project entirely (extractors under <c>data_dumps/extract/</c> emit per-table seed JSON);
|
||||||
/// file (e.g. <c>load-index-2026-05-23.json</c>) if multiple exist for the same endpoint.
|
/// only the wire-date normaliser stays here because several seed-driven importers still need
|
||||||
|
/// to canonicalise prod-shaped timestamp strings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ImporterBase
|
public static class ImporterBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Returns the parsed <c>.data</c> JsonElement for the latest <c>{endpoint}-*.json</c> file in
|
|
||||||
/// <paramref name="capturesDir"/>, or null if no file matches. Logs a warning when missing —
|
|
||||||
/// caller decides whether absence is fatal.
|
|
||||||
/// </summary>
|
|
||||||
public static JsonElement? LoadCapture(string capturesDir, string endpoint)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(capturesDir))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"[ImporterBase] Captures dir missing: {capturesDir}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string? path = Directory.EnumerateFiles(capturesDir, $"{endpoint}-*.json")
|
|
||||||
.OrderByDescending(p => p)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (path is null)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"[ImporterBase] No capture found for endpoint '{endpoint}' in {capturesDir}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var fs = File.OpenRead(path);
|
|
||||||
using var doc = JsonDocument.Parse(fs);
|
|
||||||
if (!doc.RootElement.TryGetProperty("data", out var data))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine($"[ImporterBase] Capture file {path} has no top-level 'data' property.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Clone so the JsonElement survives doc disposal.
|
|
||||||
return data.Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generic upsert by primary key. Returns (created, updated, unchanged) counts.
|
|
||||||
/// <paramref name="incoming"/> is the desired state from the capture; rows are matched by
|
|
||||||
/// <paramref name="keySelector"/>. <paramref name="applyChanges"/> mutates an existing row to
|
|
||||||
/// reflect incoming values and returns true if anything actually changed.
|
|
||||||
/// </summary>
|
|
||||||
public static (int created, int updated, int unchanged) Upsert<T, TKey>(
|
|
||||||
IEnumerable<T> incoming,
|
|
||||||
Dictionary<TKey, T> existingByKey,
|
|
||||||
Func<T, TKey> keySelector,
|
|
||||||
Action<T> addToContext,
|
|
||||||
Func<T, T, bool> applyChanges) where TKey : notnull
|
|
||||||
{
|
|
||||||
int created = 0, updated = 0, unchanged = 0;
|
|
||||||
foreach (var item in incoming)
|
|
||||||
{
|
|
||||||
var key = keySelector(item);
|
|
||||||
if (existingByKey.TryGetValue(key, out var existing))
|
|
||||||
{
|
|
||||||
if (applyChanges(existing, item)) updated++;
|
|
||||||
else unchanged++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
addToContext(item);
|
|
||||||
existingByKey[key] = item;
|
|
||||||
created++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (created, updated, unchanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Serialize a JsonElement back to compact JSON text for jsonb storage.</summary>
|
|
||||||
public static string Serialize(JsonElement el) =>
|
|
||||||
JsonSerializer.Serialize(el, new JsonSerializerOptions { WriteIndented = false });
|
|
||||||
|
|
||||||
/// <summary>Parse a wire date that may be ISO ("2026-05-23T..."), space-separated ("2026-05-23 16:32:31"), or empty.</summary>
|
/// <summary>Parse a wire date that may be ISO ("2026-05-23T..."), space-separated ("2026-05-23 16:32:31"), or empty.</summary>
|
||||||
public static DateTime ParseWireDateTime(string? s)
|
public static DateTime ParseWireDateTime(string? s)
|
||||||
{
|
{
|
||||||
@@ -91,50 +20,4 @@ public static class ImporterBase
|
|||||||
}
|
}
|
||||||
return DateTime.MinValue;
|
return DateTime.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Read a JsonElement string/number property as long, defaulting on missing/null.</summary>
|
|
||||||
public static long GetLong(JsonElement el, string prop, long fallback = 0)
|
|
||||||
{
|
|
||||||
if (!el.TryGetProperty(prop, out var v) || v.ValueKind == JsonValueKind.Null) return fallback;
|
|
||||||
if (v.ValueKind == JsonValueKind.Number) return v.GetInt64();
|
|
||||||
if (v.ValueKind == JsonValueKind.String && long.TryParse(v.GetString(), out var n)) return n;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int GetInt(JsonElement el, string prop, int fallback = 0)
|
|
||||||
{
|
|
||||||
if (!el.TryGetProperty(prop, out var v) || v.ValueKind == JsonValueKind.Null) return fallback;
|
|
||||||
if (v.ValueKind == JsonValueKind.Number) return v.GetInt32();
|
|
||||||
if (v.ValueKind == JsonValueKind.String && int.TryParse(v.GetString(), out var n)) return n;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetString(JsonElement el, string prop, string fallback = "")
|
|
||||||
{
|
|
||||||
if (!el.TryGetProperty(prop, out var v) || v.ValueKind == JsonValueKind.Null) return fallback;
|
|
||||||
return v.ValueKind == JsonValueKind.String ? v.GetString() ?? fallback : v.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool GetBool(JsonElement el, string prop, bool fallback = false)
|
|
||||||
{
|
|
||||||
if (!el.TryGetProperty(prop, out var v) || v.ValueKind == JsonValueKind.Null) return fallback;
|
|
||||||
if (v.ValueKind == JsonValueKind.True) return true;
|
|
||||||
if (v.ValueKind == JsonValueKind.False) return false;
|
|
||||||
if (v.ValueKind == JsonValueKind.Number) return v.GetInt32() != 0;
|
|
||||||
if (v.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
var s = v.GetString();
|
|
||||||
if (bool.TryParse(s, out var b)) return b;
|
|
||||||
if (int.TryParse(s, out var i)) return i != 0;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetULong(JsonElement el, string prop, ulong fallback = 0)
|
|
||||||
{
|
|
||||||
if (!el.TryGetProperty(prop, out var v) || v.ValueKind == JsonValueKind.Null) return fallback;
|
|
||||||
if (v.ValueKind == JsonValueKind.Number) return v.GetUInt64();
|
|
||||||
if (v.ValueKind == JsonValueKind.String && ulong.TryParse(v.GetString(), out var n)) return n;
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
185
SVSim.Bootstrap/Importers/MyPageGlobalsImporter.cs
Normal file
185
SVSim.Bootstrap/Importers/MyPageGlobalsImporter.cs
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of /mypage/index-derived globals from per-table seed files.
|
||||||
|
/// Banners and SpecialDeckFormats use CLEAR-AND-REWRITE semantics (no stable wire ID, capture is authoritative).
|
||||||
|
/// Colosseum and SealedSeason are singletons (Id=1). MasterPointRankingPeriod upserts by wire id.
|
||||||
|
/// </summary>
|
||||||
|
public class MyPageGlobalsImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportBannersAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<BannerSeed>(Path.Combine(seedDir, "banners.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No banner seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear-and-rewrite: banners have no stable wire ID, the capture is authoritative.
|
||||||
|
var existing = await context.Banners.ToListAsync();
|
||||||
|
context.Banners.RemoveRange(existing);
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
context.Banners.Add(new BannerEntry
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
ImageName = s.ImageName,
|
||||||
|
Click = s.Click,
|
||||||
|
Status = s.Status,
|
||||||
|
ChangeTime = s.ChangeTime,
|
||||||
|
RemainingTime = s.RemainingTime,
|
||||||
|
ImagePaths = s.ImagePaths.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "[]"
|
||||||
|
: JsonSerializer.Serialize(s.ImagePaths),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] Banners: -{existing.Count}/+{seed.Count}");
|
||||||
|
return seed.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportColosseumAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var s = SeedLoader.LoadObject<ColosseumSeed>(Path.Combine(seedDir, "colosseum.json"));
|
||||||
|
if (s is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No colosseum seed; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.Colosseums.FirstOrDefaultAsync(e => e.Id == 1);
|
||||||
|
var entry = existing ?? new ColosseumConfig { Id = 1 };
|
||||||
|
|
||||||
|
entry.ColosseumId = s.ColosseumId;
|
||||||
|
entry.ColosseumName = s.ColosseumName;
|
||||||
|
entry.CardPoolName = s.CardPoolName;
|
||||||
|
entry.DeckFormat = s.DeckFormat;
|
||||||
|
entry.StartTime = ImporterBase.ParseWireDateTime(s.StartTime);
|
||||||
|
entry.EndTime = ImporterBase.ParseWireDateTime(s.EndTime);
|
||||||
|
entry.NowRound = s.NowRound;
|
||||||
|
entry.IsDisplayTips = s.IsDisplayTips;
|
||||||
|
entry.TipsId = s.TipsId;
|
||||||
|
entry.IsColosseumPeriod = s.IsColosseumPeriod;
|
||||||
|
entry.IsRoundPeriod = s.IsRoundPeriod;
|
||||||
|
entry.IsNormalTwoPick = s.IsNormalTwoPick;
|
||||||
|
entry.IsSpecialMode = s.IsSpecialMode;
|
||||||
|
entry.IsAllCardEnabled = s.IsAllCardEnabled;
|
||||||
|
entry.SalesPeriodInfo = s.SalesPeriodInfo.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}"
|
||||||
|
: JsonSerializer.Serialize(s.SalesPeriodInfo);
|
||||||
|
|
||||||
|
if (existing is null) context.Colosseums.Add(entry);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] Colosseum: {(existing is null ? "+1" : "~1")}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportSealedAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var s = SeedLoader.LoadObject<SealedSeasonSeed>(Path.Combine(seedDir, "sealed-season.json"));
|
||||||
|
if (s is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No sealed-season seed; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.SealedSeasons.FirstOrDefaultAsync(e => e.Id == 1);
|
||||||
|
var entry = existing ?? new SealedConfig { Id = 1 };
|
||||||
|
|
||||||
|
entry.Enable = s.Enable;
|
||||||
|
entry.CrystalCost = s.CrystalCost;
|
||||||
|
entry.RupyCost = s.RupyCost;
|
||||||
|
entry.TicketCost = s.TicketCost;
|
||||||
|
entry.DeckUsingNumMin = s.DeckUsingNumMin;
|
||||||
|
entry.ScheduleId = s.ScheduleId;
|
||||||
|
entry.IsJoin = s.IsJoin;
|
||||||
|
entry.IsDeckCodeMaintenance = s.IsDeckCodeMaintenance;
|
||||||
|
entry.PackInfo = s.PackInfo.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "[]"
|
||||||
|
: JsonSerializer.Serialize(s.PackInfo);
|
||||||
|
entry.SalesPeriodInfo = s.SalesPeriodInfo.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}"
|
||||||
|
: JsonSerializer.Serialize(s.SalesPeriodInfo);
|
||||||
|
|
||||||
|
if (existing is null) context.SealedSeasons.Add(entry);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] SealedSeason: {(existing is null ? "+1" : "~1")}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportMasterPointRankingPeriodAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<MasterPointRankingPeriodSeed>(
|
||||||
|
Path.Combine(seedDir, "master-point-ranking-periods.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No master-point-ranking-period seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.MasterPointRankingPeriods.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex)
|
||||||
|
? ex : new MasterPointRankingPeriodEntry { Id = s.Id };
|
||||||
|
|
||||||
|
entry.PeriodNum = s.PeriodNum;
|
||||||
|
entry.NecessaryScore = s.NecessaryScore;
|
||||||
|
entry.BeginTime = ImporterBase.ParseWireDateTime(s.BeginTime);
|
||||||
|
entry.EndTime = ImporterBase.ParseWireDateTime(s.EndTime);
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.MasterPointRankingPeriods.Add(entry);
|
||||||
|
existing[s.Id] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] MasterPointRankingPeriod: +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportSpecialDeckFormatsAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<SpecialDeckFormatSeed>(
|
||||||
|
Path.Combine(seedDir, "special-deck-formats.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No special-deck-format seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear-and-rewrite: same semantics as banners — no stable wire ID, capture is authoritative.
|
||||||
|
var existing = await context.SpecialDeckFormats.ToListAsync();
|
||||||
|
context.SpecialDeckFormats.RemoveRange(existing);
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
context.SpecialDeckFormats.Add(new SpecialDeckFormatEntry
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
DeckFormat = s.DeckFormat,
|
||||||
|
EndTime = ImporterBase.ParseWireDateTime(s.EndTime),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] SpecialDeckFormats: -{existing.Count}/+{seed.Count}");
|
||||||
|
return seed.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
SVSim.Bootstrap/Importers/MyRotationImporter.cs
Normal file
53
SVSim.Bootstrap/Importers/MyRotationImporter.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of MyRotation reference data: settings (per rotation_id) +
|
||||||
|
/// abilities (per ability_id). Seeds come from <c>seeds/my-rotation-settings.json</c> and
|
||||||
|
/// <c>seeds/my-rotation-abilities.json</c>; the extractor pre-joins the original wire's three
|
||||||
|
/// dicts (setting, reprinted, restricted) on rotation_id, so the importer just iterates.
|
||||||
|
/// </summary>
|
||||||
|
public class MyRotationImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var settings = SeedLoader.LoadList<MyRotationSettingSeed>(Path.Combine(seedDir, "my-rotation-settings.json"));
|
||||||
|
var abilities = SeedLoader.LoadList<MyRotationAbilitySeed>(Path.Combine(seedDir, "my-rotation-abilities.json"));
|
||||||
|
|
||||||
|
if (settings.Count == 0 && abilities.Count == 0) return 0;
|
||||||
|
|
||||||
|
int sCreated = 0, sUpdated = 0;
|
||||||
|
var existingSettings = await context.MyRotationSettings.ToDictionaryAsync(e => e.Id);
|
||||||
|
foreach (var s in settings)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existingSettings.TryGetValue(s.Id, out var ex) ? ex : new MyRotationSettingEntry { Id = s.Id };
|
||||||
|
entry.CardSetIdsCsv = s.CardSetIdsCsv;
|
||||||
|
entry.AbilitiesCsv = s.AbilitiesCsv;
|
||||||
|
entry.ReprintedCardIds = s.ReprintedCardIds;
|
||||||
|
entry.RestrictedCardIds = s.RestrictedCardIds;
|
||||||
|
if (ex is null) { context.MyRotationSettings.Add(entry); existingSettings[s.Id] = entry; sCreated++; }
|
||||||
|
else sUpdated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aCreated = 0, aUpdated = 0;
|
||||||
|
var existingAbilities = await context.MyRotationAbilities.ToDictionaryAsync(e => e.Id);
|
||||||
|
foreach (var s in abilities)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
var entry = existingAbilities.TryGetValue(s.Id, out var ex) ? ex : new MyRotationAbilityEntry { Id = s.Id };
|
||||||
|
entry.Data = JsonSerializer.Serialize(s.Data);
|
||||||
|
if (ex is null) { context.MyRotationAbilities.Add(entry); existingAbilities[s.Id] = entry; aCreated++; }
|
||||||
|
else aUpdated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyRotationImporter] settings +{sCreated}/~{sUpdated}, abilities +{aCreated}/~{aUpdated}");
|
||||||
|
return sCreated + sUpdated + aCreated + aUpdated;
|
||||||
|
}
|
||||||
|
}
|
||||||
107
SVSim.Bootstrap/Importers/PackImporter.cs
Normal file
107
SVSim.Bootstrap/Importers/PackImporter.cs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Enums;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
using static SVSim.Bootstrap.Importers.ImporterBase;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of /pack/info catalog from <c>seeds/packs.json</c>. Owned collections
|
||||||
|
/// (ChildGachas, Banners) are replaced wholesale per pack (clear-then-rehydrate) -- diffing owned
|
||||||
|
/// collections by composite keys is more code than it's worth for catalog updates, and this
|
||||||
|
/// matches the wholesale-replace semantics of the previous in-line ImportPacks implementation.
|
||||||
|
/// Rows missing from the seed are LEFT INTACT.
|
||||||
|
/// </summary>
|
||||||
|
public class PackImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<PackSeed>(Path.Combine(seedDir, "packs.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PackImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.Packs
|
||||||
|
.Include(p => p.ChildGachas)
|
||||||
|
.Include(p => p.Banners)
|
||||||
|
.ToDictionaryAsync(p => p.Id);
|
||||||
|
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.ParentGachaId == 0) continue;
|
||||||
|
|
||||||
|
var pack = existing.TryGetValue(s.ParentGachaId, out var ex)
|
||||||
|
? ex : new PackConfigEntry { Id = s.ParentGachaId };
|
||||||
|
|
||||||
|
pack.BasePackId = s.BasePackId;
|
||||||
|
pack.GachaType = s.GachaType;
|
||||||
|
pack.PackCategory = (PackCategory)s.PackCategory;
|
||||||
|
pack.PosterType = s.PosterType;
|
||||||
|
pack.CommenceDate = ParseWireDateTime(s.CommenceDate);
|
||||||
|
pack.CompleteDate = ParseWireDateTime(s.CompleteDate);
|
||||||
|
pack.SleeveId = s.SleeveId;
|
||||||
|
pack.SpecialSleeveId = s.SpecialSleeveId;
|
||||||
|
pack.OverrideDrawEffectPackId = s.OverrideDrawEffectPackId;
|
||||||
|
pack.OverrideUiEffectPackId = s.OverrideUiEffectPackId;
|
||||||
|
pack.GachaDetail = s.GachaDetail;
|
||||||
|
pack.IsHide = s.IsHide;
|
||||||
|
pack.IsNew = s.IsNew;
|
||||||
|
pack.IsPreRelease = s.IsPreRelease;
|
||||||
|
pack.OpenCountLimit = s.OpenCountLimit;
|
||||||
|
pack.SalesPeriodTime = string.IsNullOrEmpty(s.SalesPeriodTime)
|
||||||
|
? null
|
||||||
|
: ParseWireDateTime(s.SalesPeriodTime);
|
||||||
|
pack.GachaPointConfig = s.GachaPoint is null ? null : new PackGachaPointConfig
|
||||||
|
{
|
||||||
|
ExchangeablePoint = s.GachaPoint.ExchangeablePoint,
|
||||||
|
IncreaseGachaPoint = s.GachaPoint.IncreaseGachaPoint,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Owned collections -- clear and rehydrate (matches the previous wholesale-replace semantics).
|
||||||
|
pack.ChildGachas.Clear();
|
||||||
|
foreach (var c in s.ChildGachas)
|
||||||
|
{
|
||||||
|
pack.ChildGachas.Add(new PackChildGachaEntry
|
||||||
|
{
|
||||||
|
GachaId = c.GachaId,
|
||||||
|
TypeDetail = c.TypeDetail,
|
||||||
|
Cost = c.Cost,
|
||||||
|
CardCount = c.CardCount,
|
||||||
|
ItemId = c.ItemId,
|
||||||
|
IsDailySingle = c.IsDailySingle,
|
||||||
|
OverrideIncreaseGachaPoint = c.OverrideIncreaseGachaPoint,
|
||||||
|
PurchaseLimitCount = c.PurchaseLimitCount,
|
||||||
|
FreeGachaCampaignId = c.FreeGachaCampaignId,
|
||||||
|
CampaignName = c.CampaignName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.Banners.Clear();
|
||||||
|
foreach (var b in s.Banners)
|
||||||
|
{
|
||||||
|
pack.Banners.Add(new PackBannerEntry
|
||||||
|
{
|
||||||
|
BannerName = b.BannerName,
|
||||||
|
DialogTitle = b.DialogTitle,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.Packs.Add(pack);
|
||||||
|
existing[s.ParentGachaId] = pack;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PackImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
SVSim.Bootstrap/Importers/PaymentItemImporter.cs
Normal file
64
SVSim.Bootstrap/Importers/PaymentItemImporter.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of Steam payment items from <c>seeds/payment-items.json</c>.
|
||||||
|
/// Rows missing from the seed are LEFT INTACT.
|
||||||
|
/// </summary>
|
||||||
|
public class PaymentItemImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(seedDir, "payment-items.json");
|
||||||
|
var seed = SeedLoader.LoadList<PaymentItemSeed>(path);
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PaymentItemImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.PaymentItems.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.RecordId == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.RecordId, out var ex)
|
||||||
|
? ex : new PaymentItemEntry { Id = s.RecordId };
|
||||||
|
|
||||||
|
entry.ProductId = s.ProductId;
|
||||||
|
entry.StoreProductId = s.StoreProductId;
|
||||||
|
entry.Name = s.Name;
|
||||||
|
entry.Text = s.Text;
|
||||||
|
entry.Price = decimal.TryParse(s.Price, NumberStyles.Number, CultureInfo.InvariantCulture, out var d) ? d : 0m;
|
||||||
|
entry.ChargeCrystalNum = s.ChargeCrystalNum;
|
||||||
|
entry.FreeCrystalNum = s.FreeCrystalNum;
|
||||||
|
entry.PurchaseLimit = s.PurchaseLimit;
|
||||||
|
entry.SpecialShopFlag = s.SpecialShopFlag;
|
||||||
|
entry.ImageName = s.ImageName;
|
||||||
|
entry.StartTime = ImporterBase.ParseWireDateTime(s.StartTime);
|
||||||
|
entry.EndTime = ImporterBase.ParseWireDateTime(s.EndTime);
|
||||||
|
entry.RemainingTime = s.RemainingTime;
|
||||||
|
entry.IsResaleProduct = s.IsResaleProduct;
|
||||||
|
entry.ResaleStartDate = string.IsNullOrWhiteSpace(s.ResaleStartDate) ? null : ImporterBase.ParseWireDateTime(s.ResaleStartDate);
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.PaymentItems.Add(entry);
|
||||||
|
existing[s.RecordId] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PaymentItemImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
SVSim.Bootstrap/Importers/PracticeOpponentImporter.cs
Normal file
59
SVSim.Bootstrap/Importers/PracticeOpponentImporter.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of practice opponents from <c>seeds/practice-opponents.json</c>.
|
||||||
|
/// Rows missing from the seed are LEFT INTACT (consistent with the previous import behavior;
|
||||||
|
/// a partial seed shouldn't silently delete entries).
|
||||||
|
/// </summary>
|
||||||
|
public class PracticeOpponentImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(seedDir, "practice-opponents.json");
|
||||||
|
var seed = SeedLoader.LoadList<PracticeOpponentSeed>(path);
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PracticeOpponentImporter] No seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.PracticeOpponents.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.PracticeId == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.PracticeId, out var ex)
|
||||||
|
? ex : new PracticeOpponentEntry { Id = s.PracticeId };
|
||||||
|
|
||||||
|
entry.TextId = s.TextId;
|
||||||
|
entry.ClassId = s.ClassId;
|
||||||
|
entry.CharaId = s.CharaId;
|
||||||
|
entry.DegreeId = s.DegreeId;
|
||||||
|
entry.AiDeckLevel = s.AiDeckLevel;
|
||||||
|
entry.AiLogicLevel = s.AiLogicLevel;
|
||||||
|
entry.AiMaxLife = s.AiMaxLife;
|
||||||
|
entry.Battle3dFieldId = s.Battle3dFieldId;
|
||||||
|
entry.IsMaintenance = s.IsMaintenance;
|
||||||
|
entry.IsCampaignPractice = s.IsCampaignPractice;
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.PracticeOpponents.Add(entry);
|
||||||
|
existing[s.PracticeId] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PracticeOpponentImporter] +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
SVSim.Bootstrap/Importers/PreReleaseInfoImporter.cs
Normal file
46
SVSim.Bootstrap/Importers/PreReleaseInfoImporter.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
using static SVSim.Bootstrap.Importers.ImporterBase;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Singleton upsert (Id=1) of the pre-release window from <c>seeds/pre-release-info.json</c>.
|
||||||
|
/// Card-id list / dict blobs are preserved verbatim into their jsonb columns; date strings go
|
||||||
|
/// through <see cref="ImporterBase.ParseWireDateTime"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class PreReleaseInfoImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var s = SeedLoader.LoadObject<PreReleaseInfoSeed>(Path.Combine(seedDir, "pre-release-info.json"));
|
||||||
|
if (s is null) return 0;
|
||||||
|
|
||||||
|
var existing = await context.PreReleaseInfos.FirstOrDefaultAsync(e => e.Id == 1);
|
||||||
|
var entry = existing ?? new PreReleaseInfo { Id = 1 };
|
||||||
|
entry.PreReleaseId = s.PreReleaseId;
|
||||||
|
entry.NextCardSetId = s.NextCardSetId;
|
||||||
|
entry.StartTime = ParseWireDateTime(s.StartTime);
|
||||||
|
entry.EndTime = ParseWireDateTime(s.EndTime);
|
||||||
|
entry.DisplayEndTime = ParseWireDateTime(s.DisplayEndTime);
|
||||||
|
entry.FreeMatchStartTime = ParseWireDateTime(s.FreeMatchStartTime);
|
||||||
|
entry.CardMasterId = s.CardMasterId;
|
||||||
|
entry.DefaultCardMasterId = s.DefaultCardMasterId;
|
||||||
|
entry.PreReleaseCardMasterId = s.PreReleaseCardMasterId;
|
||||||
|
entry.IsPreRotationFreeMatchTerm = s.IsPreRotationFreeMatchTerm;
|
||||||
|
entry.RotationCardSetIdList = s.RotationCardSetIdList.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "[]" : JsonSerializer.Serialize(s.RotationCardSetIdList);
|
||||||
|
entry.ReprintedBaseCardIds = s.ReprintedBaseCardIds.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}" : JsonSerializer.Serialize(s.ReprintedBaseCardIds);
|
||||||
|
entry.LatestReprintedBaseCardIds = s.LatestReprintedBaseCardIds.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}" : JsonSerializer.Serialize(s.LatestReprintedBaseCardIds);
|
||||||
|
if (existing is null) context.PreReleaseInfos.Add(entry);
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PreReleaseInfoImporter] {(existing is null ? "+1" : "~1")}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
142
SVSim.Bootstrap/Importers/PuzzleImporter.cs
Normal file
142
SVSim.Bootstrap/Importers/PuzzleImporter.cs
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Idempotent upsert of the basic-puzzle catalog from <c>seeds/puzzle-groups.json</c>,
|
||||||
|
/// <c>seeds/puzzles.json</c>, and <c>seeds/puzzle-missions.json</c>. Groups must be imported
|
||||||
|
/// before puzzles (FK on <see cref="PuzzleEntry.GroupId"/> -> <see cref="PuzzleGroupEntry.Id"/>).
|
||||||
|
/// Rows missing from the seed are LEFT INTACT (consistent with other per-importer seeds).
|
||||||
|
/// </summary>
|
||||||
|
public class PuzzleImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportGroupsAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(seedDir, "puzzle-groups.json");
|
||||||
|
var seed = SeedLoader.LoadList<PuzzleGroupSeed>(path);
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PuzzleImporter] No group seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.PuzzleGroups.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex)
|
||||||
|
? ex : new PuzzleGroupEntry { Id = s.Id };
|
||||||
|
|
||||||
|
entry.BasicTitleTextId = s.BasicTitleTextId;
|
||||||
|
entry.PuzzleCharaId = s.PuzzleCharaId;
|
||||||
|
entry.CharaId = s.CharaId;
|
||||||
|
entry.SortType = s.SortType;
|
||||||
|
entry.DifficultyNameListJson = s.DifficultyNameList.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "{}"
|
||||||
|
: JsonSerializer.Serialize(s.DifficultyNameList);
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.PuzzleGroups.Add(entry);
|
||||||
|
existing[s.Id] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PuzzleImporter] Groups +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportPuzzlesAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(seedDir, "puzzles.json");
|
||||||
|
var seed = SeedLoader.LoadList<PuzzleSeed>(path);
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PuzzleImporter] No puzzle seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.Puzzles.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex)
|
||||||
|
? ex : new PuzzleEntry { Id = s.Id };
|
||||||
|
|
||||||
|
entry.GroupId = s.GroupId;
|
||||||
|
entry.PuzzleDifficulty = s.PuzzleDifficulty;
|
||||||
|
entry.IsAdditional = s.IsAdditional;
|
||||||
|
entry.IsPlayable = s.IsPlayable;
|
||||||
|
entry.ReleaseConditionTextId = s.ReleaseConditionTextId;
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.Puzzles.Add(entry);
|
||||||
|
existing[s.Id] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PuzzleImporter] Puzzles +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportMissionsAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
string path = Path.Combine(seedDir, "puzzle-missions.json");
|
||||||
|
var seed = SeedLoader.LoadList<PuzzleMissionSeed>(path);
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[PuzzleImporter] No mission seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing = await context.PuzzleMissions.ToDictionaryAsync(e => e.Id);
|
||||||
|
int created = 0, updated = 0;
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
if (s.Id == 0) continue;
|
||||||
|
|
||||||
|
var entry = existing.TryGetValue(s.Id, out var ex)
|
||||||
|
? ex : new PuzzleMissionEntry { Id = s.Id };
|
||||||
|
|
||||||
|
entry.MissionName = s.MissionName;
|
||||||
|
entry.AchievedMessage = s.AchievedMessage;
|
||||||
|
entry.RequireNumber = s.RequireNumber;
|
||||||
|
entry.CampaignCommenceTime = s.CampaignCommenceTime;
|
||||||
|
entry.OrderId = s.OrderId;
|
||||||
|
entry.RewardType = s.RewardType;
|
||||||
|
entry.RewardDetailId = s.RewardDetailId;
|
||||||
|
entry.RewardNumber = s.RewardNumber;
|
||||||
|
entry.TargetPuzzleGroupId = s.TargetPuzzleGroupId;
|
||||||
|
|
||||||
|
if (ex is null)
|
||||||
|
{
|
||||||
|
context.PuzzleMissions.Add(entry);
|
||||||
|
existing[s.Id] = entry;
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
else updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[PuzzleImporter] Missions +{created}/~{updated}");
|
||||||
|
return created + updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
117
SVSim.Bootstrap/Importers/RotationConfigImporter.cs
Normal file
117
SVSim.Bootstrap/Importers/RotationConfigImporter.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Bootstrap.Models.Seed;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models;
|
||||||
|
using SVSim.Database.Models.Config;
|
||||||
|
using static SVSim.Bootstrap.Importers.ImporterBase;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes three <c>GameConfigSection</c> rows from the load-index seed split:
|
||||||
|
/// <c>seeds/rotation-config.json</c> → Rotation, <c>seeds/challenge-config.json</c> → Challenge,
|
||||||
|
/// <c>seeds/my-rotation-schedule.json</c> → MyRotationSchedule. Atomic section pattern: read the
|
||||||
|
/// existing section row (or shipped defaults), mutate the deserialized POCO, write back to
|
||||||
|
/// <c>ValueJson</c>. Re-runnable; rows missing from the seed leave the section row untouched.
|
||||||
|
/// </summary>
|
||||||
|
public class RotationConfigImporter
|
||||||
|
{
|
||||||
|
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
int touched = 0;
|
||||||
|
|
||||||
|
var rot = SeedLoader.LoadObject<RotationConfigSeed>(Path.Combine(seedDir, "rotation-config.json"));
|
||||||
|
if (rot is not null)
|
||||||
|
{
|
||||||
|
await UpsertSection<RotationConfig>(context, RotationConfig.ShippedDefaults, c =>
|
||||||
|
{
|
||||||
|
c.TsRotationId = rot.TsRotationId;
|
||||||
|
c.IsBattlePassPeriod = rot.IsBattlePassPeriod;
|
||||||
|
c.IsBeginnerMission = rot.IsBeginnerMission;
|
||||||
|
c.CardSetIdForResourceDlView = rot.CardSetIdForResourceDlView;
|
||||||
|
c.RotationCardSetIds = rot.RotationCardSetIds ?? new List<int>();
|
||||||
|
});
|
||||||
|
touched++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cc = SeedLoader.LoadObject<ChallengeConfigSeed>(Path.Combine(seedDir, "challenge-config.json"));
|
||||||
|
if (cc is not null)
|
||||||
|
{
|
||||||
|
await UpsertSection<ChallengeConfig>(context, ChallengeConfig.ShippedDefaults, c =>
|
||||||
|
{
|
||||||
|
c.UseTwoPickPremiumCard = cc.UseTwoPickPremiumCard;
|
||||||
|
c.TwoPickSleeveId = cc.TwoPickSleeveId;
|
||||||
|
});
|
||||||
|
touched++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var schedule = SeedLoader.LoadObject<MyRotationScheduleSeed>(Path.Combine(seedDir, "my-rotation-schedule.json"));
|
||||||
|
if (schedule?.Gathering is not null && schedule.FreeBattle is not null)
|
||||||
|
{
|
||||||
|
// Schedule windows are intentionally parsed WITHOUT AssumeUniversal because the seed
|
||||||
|
// strings ("2024-05-01 20:00:00") are timezone-less and the rest of the pipeline (the
|
||||||
|
// [ConfigSection] JSON round-trip + LoadController's wire mapping) treats them as
|
||||||
|
// local-kind ticks. Mirrors the legacy GlobalsImporter.TryParseScheduleWindow behavior
|
||||||
|
// — see GlobalsRepositoryTests for the round-trip assertion.
|
||||||
|
var gBegin = ParseScheduleWireDateTime(schedule.Gathering.Begin);
|
||||||
|
var gEnd = ParseScheduleWireDateTime(schedule.Gathering.End);
|
||||||
|
var fBegin = ParseScheduleWireDateTime(schedule.FreeBattle.Begin);
|
||||||
|
var fEnd = ParseScheduleWireDateTime(schedule.FreeBattle.End);
|
||||||
|
// Only commit when both windows parsed to real DateTimes — a malformed/0001 value
|
||||||
|
// would silently lock the MyRotation feature off (the original bug the section fixed).
|
||||||
|
if (gBegin != DateTime.MinValue && gEnd != DateTime.MinValue
|
||||||
|
&& fBegin != DateTime.MinValue && fEnd != DateTime.MinValue)
|
||||||
|
{
|
||||||
|
await UpsertSection<MyRotationScheduleConfig>(context, MyRotationScheduleConfig.ShippedDefaults, c =>
|
||||||
|
{
|
||||||
|
c.Gathering = new ScheduleWindow { Begin = gBegin, End = gEnd };
|
||||||
|
c.FreeBattle = new ScheduleWindow { Begin = fBegin, End = fEnd };
|
||||||
|
});
|
||||||
|
touched++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("[RotationConfigImporter] my-rotation-schedule.json windows malformed — keeping existing/shipped MyRotationSchedule.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[RotationConfigImporter] sections={touched}");
|
||||||
|
return touched;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Legacy schedule-window parse: default styles (AssumeLocal), matching the original
|
||||||
|
// GlobalsImporter.TryParseScheduleWindow. The schedule strings are timezone-less; preserving
|
||||||
|
// legacy local-kind ticks keeps the wire output byte-equivalent across the migration.
|
||||||
|
private static DateTime ParseScheduleWireDateTime(string? s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return DateTime.MinValue;
|
||||||
|
return DateTime.TryParse(s, out var dt) ? dt : DateTime.MinValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verbatim copy of GlobalsImporter.UpsertSection<T>. Kept private-static here so this
|
||||||
|
// importer can stand alone after Stage 9C strips the GlobalsImporter copy.
|
||||||
|
private static async Task UpsertSection<T>(SVSimDbContext context, Func<T> shippedDefaults, Action<T> mutate)
|
||||||
|
where T : class, new()
|
||||||
|
{
|
||||||
|
var sectionName = typeof(T).GetCustomAttributes(typeof(ConfigSectionAttribute), inherit: false)
|
||||||
|
.Cast<ConfigSectionAttribute>().FirstOrDefault()?.Name
|
||||||
|
?? throw new InvalidOperationException($"{typeof(T).Name} is missing [ConfigSection].");
|
||||||
|
|
||||||
|
var row = await context.GameConfigs.FirstOrDefaultAsync(s => s.SectionName == sectionName);
|
||||||
|
T value;
|
||||||
|
if (row is null)
|
||||||
|
{
|
||||||
|
value = shippedDefaults();
|
||||||
|
row = new GameConfigSection { SectionName = sectionName };
|
||||||
|
context.GameConfigs.Add(row);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = JsonSerializer.Deserialize<T>(row.ValueJson) ?? shippedDefaults();
|
||||||
|
}
|
||||||
|
mutate(value);
|
||||||
|
row.ValueJson = JsonSerializer.Serialize(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
SVSim.Bootstrap/Importers/RotationFlagUpdater.cs
Normal file
64
SVSim.Bootstrap/Importers/RotationFlagUpdater.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SVSim.Database;
|
||||||
|
using SVSim.Database.Models.Config;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads <see cref="RotationConfig"/> from the GameConfigs table (populated by
|
||||||
|
/// <see cref="RotationConfigImporter"/>) and flips <c>CardSet.IsInRotation</c> to match.
|
||||||
|
/// Must run after RotationConfigImporter and CardImporter — CardSets missing from the DB
|
||||||
|
/// can't be promoted (we log a warning instead of failing — the rotation flag flip is non-fatal).
|
||||||
|
/// </summary>
|
||||||
|
public class RotationFlagUpdater
|
||||||
|
{
|
||||||
|
public async Task<int> UpdateAsync(SVSimDbContext context)
|
||||||
|
{
|
||||||
|
var sectionName = typeof(RotationConfig).GetCustomAttributes(typeof(ConfigSectionAttribute), inherit: false)
|
||||||
|
.Cast<ConfigSectionAttribute>().FirstOrDefault()?.Name
|
||||||
|
?? throw new InvalidOperationException("RotationConfig missing [ConfigSection]");
|
||||||
|
|
||||||
|
var row = await context.GameConfigs.FirstOrDefaultAsync(s => s.SectionName == sectionName);
|
||||||
|
if (row is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[RotationFlagUpdater] No Rotation section in GameConfigs; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg = JsonSerializer.Deserialize<RotationConfig>(row.ValueJson);
|
||||||
|
if (cfg is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[RotationFlagUpdater] Failed to deserialize RotationConfig; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rotationSet = (cfg.RotationCardSetIds ?? new List<int>()).ToHashSet();
|
||||||
|
if (rotationSet.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[RotationFlagUpdater] RotationCardSetIds empty; no flag changes.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var allSets = await context.CardSets.ToListAsync();
|
||||||
|
int updated = 0, missing = 0;
|
||||||
|
foreach (var rid in rotationSet)
|
||||||
|
{
|
||||||
|
var set = allSets.FirstOrDefault(s => s.Id == rid);
|
||||||
|
if (set is null) { missing++; continue; }
|
||||||
|
if (!set.IsInRotation) { set.IsInRotation = true; updated++; }
|
||||||
|
}
|
||||||
|
// Demote sets not in the current rotation.
|
||||||
|
foreach (var s in allSets.Where(s => s.IsInRotation && !rotationSet.Contains(s.Id)))
|
||||||
|
{
|
||||||
|
s.IsInRotation = false;
|
||||||
|
updated++;
|
||||||
|
}
|
||||||
|
if (missing > 0)
|
||||||
|
Console.Error.WriteLine($"[RotationFlagUpdater] Warning: {missing} rotation card_set_id(s) missing from CardSets — run CardImporter first.");
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[RotationFlagUpdater] CardSet.IsInRotation ~{updated}");
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
SVSim.Bootstrap/Importers/SeedLoader.cs
Normal file
42
SVSim.Bootstrap/Importers/SeedLoader.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Importers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a JSON seed file under <c>SVSim.Bootstrap/Data/seeds/</c>. Replaces ImporterBase.LoadCapture.
|
||||||
|
/// Files are produced by extractors in <c>data_dumps/extract/</c>; the bootstrap project does not
|
||||||
|
/// transform wire formats. Missing files are non-fatal (returns empty/null) — caller decides.
|
||||||
|
/// </summary>
|
||||||
|
public static class SeedLoader
|
||||||
|
{
|
||||||
|
private static readonly JsonSerializerOptions Options = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||||
|
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
||||||
|
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||||
|
AllowTrailingCommas = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static List<T> LoadList<T>(string path)
|
||||||
|
{
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"[SeedLoader] Missing seed file: {path}");
|
||||||
|
return new List<T>();
|
||||||
|
}
|
||||||
|
using var fs = File.OpenRead(path);
|
||||||
|
return JsonSerializer.Deserialize<List<T>>(fs, Options) ?? new List<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T? LoadObject<T>(string path) where T : class
|
||||||
|
{
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"[SeedLoader] Missing seed file: {path}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
using var fs = File.OpenRead(path);
|
||||||
|
return JsonSerializer.Deserialize<T>(fs, Options);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
SVSim.Bootstrap/Models/Seed/.gitkeep
Normal file
0
SVSim.Bootstrap/Models/Seed/.gitkeep
Normal file
20
SVSim.Bootstrap/Models/Seed/ArenaSeasonSeed.cs
Normal file
20
SVSim.Bootstrap/Models/Seed/ArenaSeasonSeed.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors <c>seeds/arena-season.json</c>. Singleton (id=1) holding the Take Two arena season.
|
||||||
|
/// <c>format_info</c> is a nested JSON object stored verbatim as the entity's <c>FormatInfo</c> jsonb.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ArenaSeasonSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("mode")] public int Mode { get; set; }
|
||||||
|
[JsonPropertyName("enable")] public int Enable { get; set; }
|
||||||
|
[JsonPropertyName("cost")] public ulong Cost { get; set; }
|
||||||
|
[JsonPropertyName("rupy_cost")] public ulong RupyCost { get; set; }
|
||||||
|
[JsonPropertyName("ticket_cost")] public int TicketCost { get; set; }
|
||||||
|
[JsonPropertyName("is_join")] public bool IsJoin { get; set; }
|
||||||
|
[JsonPropertyName("format_info")] public JsonElement FormatInfo { get; set; }
|
||||||
|
}
|
||||||
17
SVSim.Bootstrap/Models/Seed/AvatarAbilitySeed.cs
Normal file
17
SVSim.Bootstrap/Models/Seed/AvatarAbilitySeed.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors <c>seeds/avatar-abilities.json</c>. One row per leader_skin_id.</summary>
|
||||||
|
public sealed class AvatarAbilitySeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("battle_start_first_player_turn_bp")] public int BattleStartFirstPlayerTurnBp { get; set; }
|
||||||
|
[JsonPropertyName("battle_start_second_player_turn_bp")] public int BattleStartSecondPlayerTurnBp { get; set; }
|
||||||
|
[JsonPropertyName("battle_start_max_life")] public int BattleStartMaxLife { get; set; }
|
||||||
|
[JsonPropertyName("ability_cost")] public string AbilityCost { get; set; } = "";
|
||||||
|
[JsonPropertyName("ability")] public string Ability { get; set; } = "";
|
||||||
|
[JsonPropertyName("passive_ability")] public string PassiveAbility { get; set; } = "";
|
||||||
|
[JsonPropertyName("ability_desc")] public string AbilityDesc { get; set; } = "";
|
||||||
|
[JsonPropertyName("passive_ability_desc")] public string PassiveAbilityDesc { get; set; } = "";
|
||||||
|
}
|
||||||
15
SVSim.Bootstrap/Models/Seed/BannerSeed.cs
Normal file
15
SVSim.Bootstrap/Models/Seed/BannerSeed.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class BannerSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("image_name")] public string ImageName { get; set; } = "";
|
||||||
|
[JsonPropertyName("click")] public string Click { get; set; } = "";
|
||||||
|
[JsonPropertyName("status")] public string Status { get; set; } = "";
|
||||||
|
[JsonPropertyName("change_time")] public int ChangeTime { get; set; }
|
||||||
|
[JsonPropertyName("remaining_time")] public int RemainingTime { get; set; }
|
||||||
|
[JsonPropertyName("image_paths")] public JsonElement ImagePaths { get; set; }
|
||||||
|
}
|
||||||
10
SVSim.Bootstrap/Models/Seed/BattlePassLevelSeed.cs
Normal file
10
SVSim.Bootstrap/Models/Seed/BattlePassLevelSeed.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors a single entry in <c>seeds/battle-pass-levels.json</c>.</summary>
|
||||||
|
public sealed class BattlePassLevelSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("level")] public int Level { get; set; }
|
||||||
|
[JsonPropertyName("required_point")] public int RequiredPoint { get; set; }
|
||||||
|
}
|
||||||
15
SVSim.Bootstrap/Models/Seed/BattlePassRewardSeed.cs
Normal file
15
SVSim.Bootstrap/Models/Seed/BattlePassRewardSeed.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors a single entry in <c>seeds/battle-pass-rewards.json</c>.</summary>
|
||||||
|
public sealed class BattlePassRewardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("season_id")] public int SeasonId { get; set; }
|
||||||
|
[JsonPropertyName("track")] public string Track { get; set; } = ""; // "normal" / "premium"
|
||||||
|
[JsonPropertyName("level")] public int Level { get; set; }
|
||||||
|
[JsonPropertyName("reward_type")] public int RewardType { get; set; }
|
||||||
|
[JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
|
||||||
|
[JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
|
||||||
|
[JsonPropertyName("is_appeal_exclusion")] public bool IsAppealExclusion { get; set; }
|
||||||
|
}
|
||||||
16
SVSim.Bootstrap/Models/Seed/BattlePassSeasonSeed.cs
Normal file
16
SVSim.Bootstrap/Models/Seed/BattlePassSeasonSeed.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors a single entry in <c>seeds/battle-pass-seasons.json</c>.</summary>
|
||||||
|
public sealed class BattlePassSeasonSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("name")] public string Name { get; set; } = "";
|
||||||
|
[JsonPropertyName("max_level")] public int MaxLevel { get; set; }
|
||||||
|
[JsonPropertyName("start_date")] public string StartDate { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_date")] public string EndDate { get; set; } = "";
|
||||||
|
[JsonPropertyName("can_purchase")] public bool CanPurchase { get; set; }
|
||||||
|
[JsonPropertyName("price_crystal")] public int PriceCrystal { get; set; }
|
||||||
|
[JsonPropertyName("description")] public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
46
SVSim.Bootstrap/Models/Seed/BuildDeckCatalogSeed.cs
Normal file
46
SVSim.Bootstrap/Models/Seed/BuildDeckCatalogSeed.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class BuildDeckCatalogSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("series_id")] public int SeriesId { get; set; }
|
||||||
|
[JsonPropertyName("order_id")] public int OrderId { get; set; }
|
||||||
|
[JsonPropertyName("is_new")] public bool IsNew { get; set; }
|
||||||
|
[JsonPropertyName("series_rewards")] public List<BuildDeckSeriesRewardSeed> SeriesRewards { get; set; } = new();
|
||||||
|
[JsonPropertyName("products")] public List<BuildDeckProductSeed> Products { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class BuildDeckSeriesRewardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("tier_index")] public int TierIndex { get; set; }
|
||||||
|
[JsonPropertyName("item_index")] public int ItemIndex { get; set; }
|
||||||
|
[JsonPropertyName("reward_type")] public int RewardType { get; set; }
|
||||||
|
[JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
|
||||||
|
[JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
|
||||||
|
[JsonPropertyName("message_id")] public int MessageId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class BuildDeckProductSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("product_id")] public int ProductId { get; set; }
|
||||||
|
[JsonPropertyName("leader_id")] public int LeaderId { get; set; }
|
||||||
|
[JsonPropertyName("deck_code")] public string DeckCode { get; set; } = "";
|
||||||
|
[JsonPropertyName("product_name")] public string ProductName { get; set; } = "";
|
||||||
|
[JsonPropertyName("featured_card_id")] public long FeaturedCardId { get; set; }
|
||||||
|
[JsonPropertyName("purchase_num_max")] public int PurchaseNumMax { get; set; }
|
||||||
|
[JsonPropertyName("intro_price_crystal")] public int? IntroPriceCrystal { get; set; }
|
||||||
|
[JsonPropertyName("regular_price_crystal")] public int? RegularPriceCrystal { get; set; }
|
||||||
|
[JsonPropertyName("intro_price_rupy")] public int? IntroPriceRupy { get; set; }
|
||||||
|
[JsonPropertyName("regular_price_rupy")] public int? RegularPriceRupy { get; set; }
|
||||||
|
[JsonPropertyName("rewards")] public List<BuildDeckProductRewardSeed> Rewards { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class BuildDeckProductRewardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("reward_index")] public int RewardIndex { get; set; }
|
||||||
|
[JsonPropertyName("reward_type")] public int RewardType { get; set; }
|
||||||
|
[JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
|
||||||
|
[JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
|
||||||
|
[JsonPropertyName("message_id")] public int MessageId { get; set; }
|
||||||
|
}
|
||||||
24
SVSim.Bootstrap/Models/Seed/ColosseumSeed.cs
Normal file
24
SVSim.Bootstrap/Models/Seed/ColosseumSeed.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class ColosseumSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; } = 1;
|
||||||
|
[JsonPropertyName("colosseum_id")] public string ColosseumId { get; set; } = "";
|
||||||
|
[JsonPropertyName("colosseum_name")] public string ColosseumName { get; set; } = "";
|
||||||
|
[JsonPropertyName("card_pool_name")] public string CardPoolName { get; set; } = "";
|
||||||
|
[JsonPropertyName("deck_format")] public string DeckFormat { get; set; } = "";
|
||||||
|
[JsonPropertyName("start_time")] public string StartTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("now_round")] public string NowRound { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_display_tips")] public string IsDisplayTips { get; set; } = "";
|
||||||
|
[JsonPropertyName("tips_id")] public string TipsId { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_colosseum_period")] public bool IsColosseumPeriod { get; set; }
|
||||||
|
[JsonPropertyName("is_round_period")] public bool IsRoundPeriod { get; set; }
|
||||||
|
[JsonPropertyName("is_normal_two_pick")] public string IsNormalTwoPick { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_special_mode")] public string IsSpecialMode { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_all_card_enabled")] public int IsAllCardEnabled { get; set; }
|
||||||
|
[JsonPropertyName("sales_period_info")] public JsonElement SalesPeriodInfo { get; set; }
|
||||||
|
}
|
||||||
11
SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs
Normal file
11
SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors <c>seeds/daily-login-bonus.json</c>. <c>bonus_data</c> preserved verbatim.</summary>
|
||||||
|
public sealed class DailyLoginBonusSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("bonus_data")] public JsonElement BonusData { get; set; }
|
||||||
|
}
|
||||||
13
SVSim.Bootstrap/Models/Seed/DefaultDeckSeed.cs
Normal file
13
SVSim.Bootstrap/Models/Seed/DefaultDeckSeed.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class DefaultDeckSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("class_id")] public int ClassId { get; set; }
|
||||||
|
[JsonPropertyName("sleeve_id")] public long SleeveId { get; set; }
|
||||||
|
[JsonPropertyName("leader_skin_id")] public int LeaderSkinId { get; set; }
|
||||||
|
[JsonPropertyName("deck_name")] public string DeckName { get; set; } = "";
|
||||||
|
[JsonPropertyName("card_id_array")] public List<long> CardIdArray { get; set; } = new();
|
||||||
|
}
|
||||||
16
SVSim.Bootstrap/Models/Seed/FeatureMaintenanceSeed.cs
Normal file
16
SVSim.Bootstrap/Models/Seed/FeatureMaintenanceSeed.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/feature-maintenances.json</c>. Source: <c>/load/index
|
||||||
|
/// data.feature_maintenance_list</c> (array of dicts; usually empty). <see cref="Data"/> is
|
||||||
|
/// the raw element so it round-trips verbatim into the entity's jsonb column.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class FeatureMaintenanceSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("feature_key")] public string FeatureKey { get; set; } = "";
|
||||||
|
[JsonPropertyName("data")] public JsonElement Data { get; set; }
|
||||||
|
}
|
||||||
12
SVSim.Bootstrap/Models/Seed/LoadingExclusionCardSeed.cs
Normal file
12
SVSim.Bootstrap/Models/Seed/LoadingExclusionCardSeed.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/loading-exclusion-cards.json</c>. Source: <c>/load/index
|
||||||
|
/// data.loading_exclusion_card_list</c> (array of card_ids).
|
||||||
|
/// </summary>
|
||||||
|
public sealed class LoadingExclusionCardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("card_id")] public long CardId { get; set; }
|
||||||
|
}
|
||||||
12
SVSim.Bootstrap/Models/Seed/MaintenanceCardSeed.cs
Normal file
12
SVSim.Bootstrap/Models/Seed/MaintenanceCardSeed.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/maintenance-cards.json</c>. Source: <c>/load/index
|
||||||
|
/// data.maintenance_card_list</c> (array of card_ids; usually empty).
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MaintenanceCardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("card_id")] public long CardId { get; set; }
|
||||||
|
}
|
||||||
12
SVSim.Bootstrap/Models/Seed/MasterPointRankingPeriodSeed.cs
Normal file
12
SVSim.Bootstrap/Models/Seed/MasterPointRankingPeriodSeed.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class MasterPointRankingPeriodSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("period_num")] public int PeriodNum { get; set; }
|
||||||
|
[JsonPropertyName("necessary_score")] public long NecessaryScore { get; set; }
|
||||||
|
[JsonPropertyName("begin_time")] public string BeginTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
}
|
||||||
11
SVSim.Bootstrap/Models/Seed/MyRotationAbilitySeed.cs
Normal file
11
SVSim.Bootstrap/Models/Seed/MyRotationAbilitySeed.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>Mirrors <c>seeds/my-rotation-abilities.json</c>. <c>data</c> is preserved as raw JSON.</summary>
|
||||||
|
public sealed class MyRotationAbilitySeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("data")] public JsonElement Data { get; set; }
|
||||||
|
}
|
||||||
18
SVSim.Bootstrap/Models/Seed/MyRotationSettingSeed.cs
Normal file
18
SVSim.Bootstrap/Models/Seed/MyRotationSettingSeed.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors <c>seeds/my-rotation-settings.json</c>. The extractor pre-joins
|
||||||
|
/// <c>my_rotation_info.{setting, reprinted_base_card_ids, restricted_base_card_id_list}</c> on
|
||||||
|
/// rotation_id into one flat list. <c>reprinted_card_ids</c> and <c>restricted_card_ids</c> are
|
||||||
|
/// pre-serialized JSON strings (verbatim from the wire) — the importer stores them verbatim.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MyRotationSettingSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("card_set_ids_csv")] public string CardSetIdsCsv { get; set; } = "";
|
||||||
|
[JsonPropertyName("abilities_csv")] public string AbilitiesCsv { get; set; } = "";
|
||||||
|
[JsonPropertyName("reprinted_card_ids")] public string ReprintedCardIds { get; set; } = "[]";
|
||||||
|
[JsonPropertyName("restricted_card_ids")] public string RestrictedCardIds { get; set; } = "[]";
|
||||||
|
}
|
||||||
53
SVSim.Bootstrap/Models/Seed/PackSeed.cs
Normal file
53
SVSim.Bootstrap/Models/Seed/PackSeed.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PackSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("parent_gacha_id")] public int ParentGachaId { get; set; }
|
||||||
|
[JsonPropertyName("base_pack_id")] public int BasePackId { get; set; }
|
||||||
|
[JsonPropertyName("gacha_type")] public int GachaType { get; set; }
|
||||||
|
[JsonPropertyName("pack_category")] public int PackCategory { get; set; }
|
||||||
|
[JsonPropertyName("poster_type")] public int PosterType { get; set; }
|
||||||
|
[JsonPropertyName("commence_date")] public string CommenceDate { get; set; } = "";
|
||||||
|
[JsonPropertyName("complete_date")] public string CompleteDate { get; set; } = "";
|
||||||
|
[JsonPropertyName("sleeve_id")] public int SleeveId { get; set; }
|
||||||
|
[JsonPropertyName("special_sleeve_id")] public int SpecialSleeveId { get; set; }
|
||||||
|
[JsonPropertyName("override_draw_effect_pack_id")] public int OverrideDrawEffectPackId { get; set; }
|
||||||
|
[JsonPropertyName("override_ui_effect_pack_id")] public int OverrideUiEffectPackId { get; set; }
|
||||||
|
[JsonPropertyName("gacha_detail")] public string GachaDetail { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_hide")] public bool IsHide { get; set; }
|
||||||
|
[JsonPropertyName("is_new")] public bool IsNew { get; set; }
|
||||||
|
[JsonPropertyName("is_pre_release")] public bool IsPreRelease { get; set; }
|
||||||
|
[JsonPropertyName("open_count_limit")] public int OpenCountLimit { get; set; }
|
||||||
|
[JsonPropertyName("sales_period_time")] public string? SalesPeriodTime { get; set; }
|
||||||
|
[JsonPropertyName("gacha_point")] public PackGachaPointSeed? GachaPoint { get; set; }
|
||||||
|
[JsonPropertyName("child_gachas")] public List<PackChildGachaSeed> ChildGachas { get; set; } = new();
|
||||||
|
[JsonPropertyName("banners")] public List<PackBannerSeed> Banners { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class PackGachaPointSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("exchangeable_point")] public int ExchangeablePoint { get; set; }
|
||||||
|
[JsonPropertyName("increase_gacha_point")] public int IncreaseGachaPoint { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class PackChildGachaSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("gacha_id")] public int GachaId { get; set; }
|
||||||
|
[JsonPropertyName("type_detail")] public int TypeDetail { get; set; }
|
||||||
|
[JsonPropertyName("cost")] public int Cost { get; set; }
|
||||||
|
[JsonPropertyName("card_count")] public int CardCount { get; set; } = 8;
|
||||||
|
[JsonPropertyName("item_id")] public long? ItemId { get; set; }
|
||||||
|
[JsonPropertyName("is_daily_single")] public bool IsDailySingle { get; set; }
|
||||||
|
[JsonPropertyName("override_increase_gacha_point")] public int OverrideIncreaseGachaPoint { get; set; }
|
||||||
|
[JsonPropertyName("purchase_limit_count")] public int PurchaseLimitCount { get; set; }
|
||||||
|
[JsonPropertyName("free_gacha_campaign_id")] public int? FreeGachaCampaignId { get; set; }
|
||||||
|
[JsonPropertyName("campaign_name")] public string? CampaignName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class PackBannerSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("banner_name")] public string BannerName { get; set; } = "";
|
||||||
|
[JsonPropertyName("dialog_title")] public string DialogTitle { get; set; } = "";
|
||||||
|
}
|
||||||
23
SVSim.Bootstrap/Models/Seed/PaymentItemSeed.cs
Normal file
23
SVSim.Bootstrap/Models/Seed/PaymentItemSeed.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PaymentItemSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("record_id")] public int RecordId { get; set; }
|
||||||
|
[JsonPropertyName("product_id")] public int ProductId { get; set; }
|
||||||
|
[JsonPropertyName("store_product_id")] public long StoreProductId { get; set; }
|
||||||
|
[JsonPropertyName("name")] public string Name { get; set; } = "";
|
||||||
|
[JsonPropertyName("text")] public string Text { get; set; } = "";
|
||||||
|
[JsonPropertyName("price")] public string Price { get; set; } = "0";
|
||||||
|
[JsonPropertyName("charge_crystal_num")] public int ChargeCrystalNum { get; set; }
|
||||||
|
[JsonPropertyName("free_crystal_num")] public int FreeCrystalNum { get; set; }
|
||||||
|
[JsonPropertyName("purchase_limit")] public int PurchaseLimit { get; set; }
|
||||||
|
[JsonPropertyName("special_shop_flag")] public int SpecialShopFlag { get; set; }
|
||||||
|
[JsonPropertyName("image_name")] public string ImageName { get; set; } = "";
|
||||||
|
[JsonPropertyName("start_time")] public string StartTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("remaining_time")] public int RemainingTime { get; set; }
|
||||||
|
[JsonPropertyName("is_resale_product")] public int IsResaleProduct { get; set; }
|
||||||
|
[JsonPropertyName("resale_start_date")] public string ResaleStartDate { get; set; } = "";
|
||||||
|
}
|
||||||
18
SVSim.Bootstrap/Models/Seed/PracticeOpponentSeed.cs
Normal file
18
SVSim.Bootstrap/Models/Seed/PracticeOpponentSeed.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PracticeOpponentSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("practice_id")] public int PracticeId { get; set; }
|
||||||
|
[JsonPropertyName("text_id")] public string TextId { get; set; } = "";
|
||||||
|
[JsonPropertyName("class_id")] public int ClassId { get; set; }
|
||||||
|
[JsonPropertyName("chara_id")] public int CharaId { get; set; }
|
||||||
|
[JsonPropertyName("degree_id")] public int DegreeId { get; set; }
|
||||||
|
[JsonPropertyName("ai_deck_level")] public int AiDeckLevel { get; set; }
|
||||||
|
[JsonPropertyName("ai_logic_level")] public int AiLogicLevel { get; set; }
|
||||||
|
[JsonPropertyName("ai_max_life")] public int AiMaxLife { get; set; }
|
||||||
|
[JsonPropertyName("battle3dfield_id")] public string Battle3dFieldId { get; set; } = "1";
|
||||||
|
[JsonPropertyName("is_maintenance")] public bool IsMaintenance { get; set; }
|
||||||
|
[JsonPropertyName("is_campaign_practice")] public bool IsCampaignPractice { get; set; }
|
||||||
|
}
|
||||||
25
SVSim.Bootstrap/Models/Seed/PreReleaseInfoSeed.cs
Normal file
25
SVSim.Bootstrap/Models/Seed/PreReleaseInfoSeed.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors <c>seeds/pre-release-info.json</c>. Singleton (id=1). Card-id lists are kept as raw
|
||||||
|
/// JSON elements so they round-trip verbatim into the entity's jsonb columns.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class PreReleaseInfoSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("pre_release_id")] public string PreReleaseId { get; set; } = "";
|
||||||
|
[JsonPropertyName("next_card_set_id")] public string NextCardSetId { get; set; } = "";
|
||||||
|
[JsonPropertyName("start_time")] public string StartTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("display_end_time")] public string DisplayEndTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("free_match_start_time")] public string FreeMatchStartTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("card_master_id")] public int CardMasterId { get; set; }
|
||||||
|
[JsonPropertyName("default_card_master_id")] public string DefaultCardMasterId { get; set; } = "";
|
||||||
|
[JsonPropertyName("pre_release_card_master_id")] public string PreReleaseCardMasterId { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_pre_rotation_free_match_term")] public bool IsPreRotationFreeMatchTerm { get; set; }
|
||||||
|
[JsonPropertyName("rotation_card_set_id_list")] public JsonElement RotationCardSetIdList { get; set; }
|
||||||
|
[JsonPropertyName("reprinted_base_card_ids")] public JsonElement ReprintedBaseCardIds { get; set; }
|
||||||
|
[JsonPropertyName("latest_reprinted_base_card_ids")] public JsonElement LatestReprintedBaseCardIds { get; set; }
|
||||||
|
}
|
||||||
14
SVSim.Bootstrap/Models/Seed/PuzzleGroupSeed.cs
Normal file
14
SVSim.Bootstrap/Models/Seed/PuzzleGroupSeed.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PuzzleGroupSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("basic_title_text_id")] public string BasicTitleTextId { get; set; } = "";
|
||||||
|
[JsonPropertyName("puzzle_chara_id")] public int PuzzleCharaId { get; set; }
|
||||||
|
[JsonPropertyName("chara_id")] public int CharaId { get; set; }
|
||||||
|
[JsonPropertyName("sort_type")] public int SortType { get; set; }
|
||||||
|
[JsonPropertyName("difficulty_name_list")] public JsonElement DifficultyNameList { get; set; }
|
||||||
|
}
|
||||||
17
SVSim.Bootstrap/Models/Seed/PuzzleMissionSeed.cs
Normal file
17
SVSim.Bootstrap/Models/Seed/PuzzleMissionSeed.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PuzzleMissionSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("mission_name")] public string MissionName { get; set; } = "";
|
||||||
|
[JsonPropertyName("achieved_message")] public string AchievedMessage { get; set; } = "";
|
||||||
|
[JsonPropertyName("require_number")] public int RequireNumber { get; set; }
|
||||||
|
[JsonPropertyName("campaign_commence_time")] public long CampaignCommenceTime { get; set; }
|
||||||
|
[JsonPropertyName("order_id")] public int OrderId { get; set; }
|
||||||
|
[JsonPropertyName("reward_type")] public int RewardType { get; set; }
|
||||||
|
[JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
|
||||||
|
[JsonPropertyName("reward_number")] public int RewardNumber { get; set; }
|
||||||
|
[JsonPropertyName("target_puzzle_group_id")] public int? TargetPuzzleGroupId { get; set; }
|
||||||
|
}
|
||||||
13
SVSim.Bootstrap/Models/Seed/PuzzleSeed.cs
Normal file
13
SVSim.Bootstrap/Models/Seed/PuzzleSeed.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class PuzzleSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("group_id")] public int GroupId { get; set; }
|
||||||
|
[JsonPropertyName("puzzle_difficulty")] public int PuzzleDifficulty { get; set; }
|
||||||
|
[JsonPropertyName("is_additional")] public bool IsAdditional { get; set; }
|
||||||
|
[JsonPropertyName("is_playable")] public bool IsPlayable { get; set; }
|
||||||
|
[JsonPropertyName("release_condition_text_id")] public string ReleaseConditionTextId { get; set; } = "";
|
||||||
|
}
|
||||||
12
SVSim.Bootstrap/Models/Seed/ReprintedCardSeed.cs
Normal file
12
SVSim.Bootstrap/Models/Seed/ReprintedCardSeed.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/reprinted-cards.json</c>. Source: <c>/load/index
|
||||||
|
/// data.reprinted_base_card_ids</c> (dict or list of card_ids).
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ReprintedCardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("card_id")] public long CardId { get; set; }
|
||||||
|
}
|
||||||
41
SVSim.Bootstrap/Models/Seed/RotationConfigSeed.cs
Normal file
41
SVSim.Bootstrap/Models/Seed/RotationConfigSeed.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors <c>seeds/rotation-config.json</c>. Drives the Rotation <c>GameConfigSection</c>.
|
||||||
|
/// Note: <c>rotation_card_set_ids</c> is the rotation CardSet flag list — consumed by
|
||||||
|
/// RotationFlagUpdater in Stage 9C, not by RotationConfigImporter.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class RotationConfigSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("ts_rotation_id")] public string TsRotationId { get; set; } = "";
|
||||||
|
[JsonPropertyName("is_battle_pass_period")] public bool IsBattlePassPeriod { get; set; }
|
||||||
|
[JsonPropertyName("is_beginner_mission")] public bool IsBeginnerMission { get; set; }
|
||||||
|
[JsonPropertyName("card_set_id_for_resource_dl_view")] public int CardSetIdForResourceDlView { get; set; }
|
||||||
|
[JsonPropertyName("rotation_card_set_ids")] public List<int> RotationCardSetIds { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Mirrors <c>seeds/challenge-config.json</c>. Drives the Challenge <c>GameConfigSection</c>.</summary>
|
||||||
|
public sealed class ChallengeConfigSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("use_two_pick_premium_card")] public bool UseTwoPickPremiumCard { get; set; }
|
||||||
|
[JsonPropertyName("two_pick_sleeve_id")] public long TwoPickSleeveId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors <c>seeds/my-rotation-schedule.json</c>. Drives the MyRotationSchedule
|
||||||
|
/// <c>GameConfigSection</c>. The extractor pre-joins <c>gathering</c> and <c>free_battle</c>
|
||||||
|
/// from <c>my_rotation_info.schedules</c> into two top-level fields.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MyRotationScheduleSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("gathering")] public ScheduleWindowSeed? Gathering { get; set; }
|
||||||
|
[JsonPropertyName("free_battle")] public ScheduleWindowSeed? FreeBattle { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ScheduleWindowSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("begin")] public string Begin { get; set; } = "";
|
||||||
|
[JsonPropertyName("end")] public string End { get; set; } = "";
|
||||||
|
}
|
||||||
19
SVSim.Bootstrap/Models/Seed/SealedSeasonSeed.cs
Normal file
19
SVSim.Bootstrap/Models/Seed/SealedSeasonSeed.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class SealedSeasonSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; } = 1;
|
||||||
|
[JsonPropertyName("enable")] public int Enable { get; set; }
|
||||||
|
[JsonPropertyName("crystal_cost")] public int CrystalCost { get; set; }
|
||||||
|
[JsonPropertyName("rupy_cost")] public int RupyCost { get; set; }
|
||||||
|
[JsonPropertyName("ticket_cost")] public int TicketCost { get; set; }
|
||||||
|
[JsonPropertyName("deck_using_num_min")] public int DeckUsingNumMin { get; set; }
|
||||||
|
[JsonPropertyName("schedule_id")] public int ScheduleId { get; set; }
|
||||||
|
[JsonPropertyName("is_join")] public bool IsJoin { get; set; }
|
||||||
|
[JsonPropertyName("is_deck_code_maintenance")] public bool IsDeckCodeMaintenance { get; set; }
|
||||||
|
[JsonPropertyName("pack_info")] public JsonElement PackInfo { get; set; }
|
||||||
|
[JsonPropertyName("sales_period_info")] public JsonElement SalesPeriodInfo { get; set; }
|
||||||
|
}
|
||||||
10
SVSim.Bootstrap/Models/Seed/SpecialDeckFormatSeed.cs
Normal file
10
SVSim.Bootstrap/Models/Seed/SpecialDeckFormatSeed.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class SpecialDeckFormatSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("deck_format")] public string DeckFormat { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
}
|
||||||
13
SVSim.Bootstrap/Models/Seed/SpotCardSeed.cs
Normal file
13
SVSim.Bootstrap/Models/Seed/SpotCardSeed.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/spot-cards.json</c>. Source: <c>/load/index data.spot_cards</c>
|
||||||
|
/// — extractor reshapes the wire dict {card_id: cost} into a list of {card_id, cost} rows.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SpotCardSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("card_id")] public long CardId { get; set; }
|
||||||
|
[JsonPropertyName("cost")] public int Cost { get; set; }
|
||||||
|
}
|
||||||
13
SVSim.Bootstrap/Models/Seed/UnlimitedRestrictionSeed.cs
Normal file
13
SVSim.Bootstrap/Models/Seed/UnlimitedRestrictionSeed.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mirrors one entry of <c>seeds/unlimited-restrictions.json</c>. Source: <c>/load/index
|
||||||
|
/// data.unlimited_restricted_base_card_id_list</c> (dict {card_id: restriction_value}).
|
||||||
|
/// </summary>
|
||||||
|
public sealed class UnlimitedRestrictionSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("card_id")] public long CardId { get; set; }
|
||||||
|
[JsonPropertyName("restriction_value")] public int RestrictionValue { get; set; }
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ public static class Program
|
|||||||
Console.WriteLine($"[Bootstrap] Connection: {RedactPassword(opts.ConnectionString)}");
|
Console.WriteLine($"[Bootstrap] Connection: {RedactPassword(opts.ConnectionString)}");
|
||||||
Console.WriteLine($"[Bootstrap] Reference CSVs: {opts.ReferenceDataDir}");
|
Console.WriteLine($"[Bootstrap] Reference CSVs: {opts.ReferenceDataDir}");
|
||||||
Console.WriteLine($"[Bootstrap] Cards file: {opts.CardsFile}");
|
Console.WriteLine($"[Bootstrap] Cards file: {opts.CardsFile}");
|
||||||
Console.WriteLine($"[Bootstrap] Captures: {opts.CapturesDir}");
|
Console.WriteLine($"[Bootstrap] Seeds: {opts.SeedDir}");
|
||||||
|
|
||||||
var dbOptions = new DbContextOptionsBuilder<SVSimDbContext>()
|
var dbOptions = new DbContextOptionsBuilder<SVSimDbContext>()
|
||||||
.UseNpgsql(opts.ConnectionString)
|
.UseNpgsql(opts.ConnectionString)
|
||||||
@@ -43,7 +43,7 @@ public static class Program
|
|||||||
await using var context = new SVSimDbContext(NullLogger<SVSimDbContext>.Instance, dbOptions);
|
await using var context = new SVSimDbContext(NullLogger<SVSimDbContext>.Instance, dbOptions);
|
||||||
|
|
||||||
// Bootstrap applies pending migrations first — migrations are now DDL-only, all data
|
// Bootstrap applies pending migrations first — migrations are now DDL-only, all data
|
||||||
// (reference tables, cards, card cosmetic rewards, prod-captured globals, game config)
|
// (reference tables, cards, card cosmetic rewards, per-table seed globals, game config)
|
||||||
// is loaded by importers below. This means a freshly migrated DB is structure-only;
|
// is loaded by importers below. This means a freshly migrated DB is structure-only;
|
||||||
// every importer is idempotent so re-running is safe.
|
// every importer is idempotent so re-running is safe.
|
||||||
Console.WriteLine("[Bootstrap] Applying pending migrations...");
|
Console.WriteLine("[Bootstrap] Applying pending migrations...");
|
||||||
@@ -75,14 +75,46 @@ public static class Program
|
|||||||
|
|
||||||
if (!opts.SkipGlobals)
|
if (!opts.SkipGlobals)
|
||||||
{
|
{
|
||||||
await new GlobalsImporter().ImportAllAsync(context, opts.CapturesDir);
|
// Per-domain seed pipeline. Each importer reads a per-table JSON seed file under
|
||||||
|
// SVSim.Bootstrap/Data/seeds/ produced by an extractor in data_dumps/extract/.
|
||||||
|
//
|
||||||
|
// RotationConfigImporter writes the Rotation GameConfig section that RotationFlagUpdater
|
||||||
|
// reads; CardImporter ran earlier in the !SkipCards block so CardSets are populated.
|
||||||
|
await new RotationConfigImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new MyRotationImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new AvatarAbilityImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new ArenaSeasonImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new BattlePassImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new BattlePassSeasonImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new BattlePassRewardImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new DailyLoginBonusImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new PreReleaseInfoImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new CardListsImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new RotationFlagUpdater().UpdateAsync(context);
|
||||||
|
|
||||||
|
await new PracticeOpponentImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new PaymentItemImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
var puzzleImporter = new PuzzleImporter();
|
||||||
|
await puzzleImporter.ImportGroupsAsync(context, opts.SeedDir);
|
||||||
|
await puzzleImporter.ImportPuzzlesAsync(context, opts.SeedDir);
|
||||||
|
await puzzleImporter.ImportMissionsAsync(context, opts.SeedDir);
|
||||||
|
|
||||||
|
var mypage = new MyPageGlobalsImporter();
|
||||||
|
await mypage.ImportBannersAsync(context, opts.SeedDir);
|
||||||
|
await mypage.ImportColosseumAsync(context, opts.SeedDir);
|
||||||
|
await mypage.ImportSealedAsync(context, opts.SeedDir);
|
||||||
|
await mypage.ImportMasterPointRankingPeriodAsync(context, opts.SeedDir);
|
||||||
|
await mypage.ImportSpecialDeckFormatsAsync(context, opts.SeedDir);
|
||||||
|
|
||||||
|
await new DefaultDeckImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
await new PackImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
|
||||||
// BuildDeck pipeline: series CSV → catalog JSON → package CSV. Catalog must run after
|
// BuildDeck pipeline: series CSV → catalog JSON → package CSV. Catalog must run after
|
||||||
// series CSV (FK on products → series) and before package CSV (so the catalog-side
|
// series CSV (FK on products → series) and before package CSV (so the catalog-side
|
||||||
// enriched rows take precedence over stub creation).
|
// enriched rows take precedence over stub creation).
|
||||||
var buildDeck = new BuildDeckImporter();
|
var buildDeck = new BuildDeckImporter();
|
||||||
await buildDeck.ImportSeriesAsync(context, opts.ReferenceDataDir);
|
await buildDeck.ImportSeriesAsync(context, opts.ReferenceDataDir);
|
||||||
await buildDeck.ImportCatalogAsync(context, opts.CapturesDir);
|
await buildDeck.ImportCatalogAsync(context, opts.SeedDir);
|
||||||
await buildDeck.ImportPackageAsync(context, opts.ReferenceDataDir);
|
await buildDeck.ImportPackageAsync(context, opts.ReferenceDataDir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -106,7 +138,6 @@ public static class Program
|
|||||||
private static BootstrapOptions? ParseArgs(string[] args)
|
private static BootstrapOptions? ParseArgs(string[] args)
|
||||||
{
|
{
|
||||||
string? cards = null;
|
string? cards = null;
|
||||||
string? captures = null;
|
|
||||||
string? referenceDataDir = null;
|
string? referenceDataDir = null;
|
||||||
string? connection = null;
|
string? connection = null;
|
||||||
bool skipReference = false;
|
bool skipReference = false;
|
||||||
@@ -122,7 +153,6 @@ public static class Program
|
|||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case "--cards": cards = NextArg(args, ref i); break;
|
case "--cards": cards = NextArg(args, ref i); break;
|
||||||
case "--captures": captures = NextArg(args, ref i); break;
|
|
||||||
case "--reference-data-dir": referenceDataDir = NextArg(args, ref i); break;
|
case "--reference-data-dir": referenceDataDir = NextArg(args, ref i); break;
|
||||||
case "--connection-string": connection = NextArg(args, ref i); break;
|
case "--connection-string": connection = NextArg(args, ref i); break;
|
||||||
case "--skip-reference": skipReference = true; break;
|
case "--skip-reference": skipReference = true; break;
|
||||||
@@ -140,26 +170,25 @@ public static class Program
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All bootstrap inputs ship in-project under SVSim.Bootstrap/Data/, copied next to the
|
// All bootstrap inputs ship in-project under SVSim.Bootstrap/Data/, copied next to the
|
||||||
// binary on build. The --cards/--captures/--reference-data-dir flags are ad-hoc overrides
|
// binary on build. The --cards/--reference-data-dir flags are ad-hoc overrides
|
||||||
// (e.g. point at a fresh loader dump before promoting it into the project).
|
// (e.g. point at a fresh loader dump before promoting it into the project).
|
||||||
string baseDir = AppContext.BaseDirectory;
|
string baseDir = AppContext.BaseDirectory;
|
||||||
string shippedDataDir = Path.Combine(baseDir, "Data");
|
string shippedDataDir = Path.Combine(baseDir, "Data");
|
||||||
string shippedCaptures = Path.Combine(shippedDataDir, "prod-captures");
|
|
||||||
string shippedCardsFile = Path.Combine(shippedDataDir, "cards.json");
|
string shippedCardsFile = Path.Combine(shippedDataDir, "cards.json");
|
||||||
|
|
||||||
string cardsFile = cards ?? positionalCards ?? shippedCardsFile;
|
string cardsFile = cards ?? positionalCards ?? shippedCardsFile;
|
||||||
string capturesDir = captures ?? shippedCaptures;
|
|
||||||
string refDir = referenceDataDir ?? shippedDataDir;
|
string refDir = referenceDataDir ?? shippedDataDir;
|
||||||
string shippedStoryDir = Path.Combine(shippedDataDir, "story");
|
string shippedStoryDir = Path.Combine(shippedDataDir, "story");
|
||||||
string storyDir = storyDataDir ?? shippedStoryDir;
|
string storyDir = storyDataDir ?? shippedStoryDir;
|
||||||
|
string shippedSeedDir = Path.Combine(shippedDataDir, "seeds");
|
||||||
|
|
||||||
string connStr = connection
|
string connStr = connection
|
||||||
?? Environment.GetEnvironmentVariable("NPGSQL_CONNECTION")
|
?? Environment.GetEnvironmentVariable("NPGSQL_CONNECTION")
|
||||||
?? DefaultConnectionString;
|
?? DefaultConnectionString;
|
||||||
|
|
||||||
return new BootstrapOptions(
|
return new BootstrapOptions(
|
||||||
cardsFile, capturesDir, refDir, connStr, skipReference, skipCards, skipGlobals,
|
cardsFile, refDir, connStr, skipReference, skipCards, skipGlobals,
|
||||||
skipStory, storyDir);
|
skipStory, storyDir, shippedSeedDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string NextArg(string[] args, ref int i)
|
private static string NextArg(string[] args, ref int i)
|
||||||
@@ -181,28 +210,30 @@ public static class Program
|
|||||||
" loader dump) — promote into Data/ when you're ready to make it permanent.\n" +
|
" loader dump) — promote into Data/ when you're ready to make it permanent.\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" --cards <file> Override path to cards.json (default: shipped Data/cards.json)\n" +
|
" --cards <file> Override path to cards.json (default: shipped Data/cards.json)\n" +
|
||||||
" --captures <dir> Override path to prod-captures directory\n" +
|
|
||||||
" (default: shipped Data/prod-captures)\n" +
|
|
||||||
" --reference-data-dir <dir> Override reference CSV directory (default: shipped Data/)\n" +
|
" --reference-data-dir <dir> Override reference CSV directory (default: shipped Data/)\n" +
|
||||||
" --connection-string <conn> Postgres connection (or NPGSQL_CONNECTION env var,\n" +
|
" --connection-string <conn> Postgres connection (or NPGSQL_CONNECTION env var,\n" +
|
||||||
$" then \"{DefaultConnectionString}\")\n" +
|
$" then \"{DefaultConnectionString}\")\n" +
|
||||||
" --skip-reference Skip reference-data import (classes, sleeves, ranks, ...)\n" +
|
" --skip-reference Skip reference-data import (classes, sleeves, ranks, ...)\n" +
|
||||||
" --skip-cards Skip card + card-cosmetic-reward import\n" +
|
" --skip-cards Skip card + card-cosmetic-reward import\n" +
|
||||||
" --skip-globals Skip prod-captured globals import\n" +
|
" --skip-globals Skip seed-driven globals import (per-table JSON under Data/seeds)\n" +
|
||||||
" --story-data-dir <dir> Override story data directory (default: shipped Data/story)\n" +
|
" --story-data-dir <dir> Override story data directory (default: shipped Data/story)\n" +
|
||||||
" --skip-story Skip story import (worlds/sections/chapters/sbs)\n" +
|
" --skip-story Skip story import (worlds/sections/chapters/sbs)\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
|
"Capture-derived seeds are produced by extractors under data_dumps/extract/* and\n" +
|
||||||
|
"checked into SVSim.Bootstrap/Data/seeds/. The bootstrap project never parses wire\n" +
|
||||||
|
"captures directly — refresh seeds by re-running the relevant extractor.\n" +
|
||||||
|
"\n" +
|
||||||
"Back-compat: `svsim-bootstrap <cards.json> [connection]` still works (positional).");
|
"Back-compat: `svsim-bootstrap <cards.json> [connection]` still works (positional).");
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed record BootstrapOptions(
|
private sealed record BootstrapOptions(
|
||||||
string CardsFile,
|
string CardsFile,
|
||||||
string CapturesDir,
|
|
||||||
string ReferenceDataDir,
|
string ReferenceDataDir,
|
||||||
string ConnectionString,
|
string ConnectionString,
|
||||||
bool SkipReference,
|
bool SkipReference,
|
||||||
bool SkipCards,
|
bool SkipCards,
|
||||||
bool SkipGlobals,
|
bool SkipGlobals,
|
||||||
bool SkipStory,
|
bool SkipStory,
|
||||||
string StoryDataDir);
|
string StoryDataDir,
|
||||||
|
string SeedDir);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Data\prod-captures\*.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="Data\*.csv">
|
<Content Include="Data\*.csv">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@@ -27,6 +24,9 @@
|
|||||||
<Content Include="Data\story\*.json">
|
<Content Include="Data\story\*.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Data\seeds\**\*.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
11
SVSim.Database/Enums/BattlePassTrack.cs
Normal file
11
SVSim.Database/Enums/BattlePassTrack.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace SVSim.Database.Enums;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reward track on a battle pass season. Wire shape uses the section keys
|
||||||
|
/// <c>"normal"</c> and <c>"premium"</c> under <c>reward_info</c>.
|
||||||
|
/// </summary>
|
||||||
|
public enum BattlePassTrack
|
||||||
|
{
|
||||||
|
Normal = 0,
|
||||||
|
Premium = 1,
|
||||||
|
}
|
||||||
2808
SVSim.Database/Migrations/20260527015510_RefactorBattlePassLevels.Designer.cs
generated
Normal file
2808
SVSim.Database/Migrations/20260527015510_RefactorBattlePassLevels.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace SVSim.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class RefactorBattlePassLevels : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(name: "RewardData", table: "BattlePassLevels");
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "RequiredPoint", table: "BattlePassLevels",
|
||||||
|
type: "integer", nullable: false, defaultValue: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(name: "RequiredPoint", table: "BattlePassLevels");
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "RewardData", table: "BattlePassLevels",
|
||||||
|
type: "jsonb", nullable: false, defaultValue: "{}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2984
SVSim.Database/Migrations/20260527023819_AddBattlePass.Designer.cs
generated
Normal file
2984
SVSim.Database/Migrations/20260527023819_AddBattlePass.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user