Update to v1.3

This commit is contained in:
Lost-MSth
2020-10-09 16:57:52 +08:00
committed by GitHub
parent 2068a36dc1
commit 78c2ef6836
44 changed files with 9669 additions and 0 deletions

Binary file not shown.

BIN
v1.3/database/arcsong.db Normal file

Binary file not shown.

View File

@@ -0,0 +1,251 @@
import sqlite3
import hashlib
import time
# 数据库初始化文件删掉arcaea_database.db文件后运行即可谨慎使用
conn = sqlite3.connect('arcaea_database.db')
c = conn.cursor()
c.execute('''create table if not exists user(user_id int primary key,
name text unique,
password text not null,
join_date char(20),
user_code char(10),
rating_ptt int,
character_id int,
is_skill_sealed int,
is_char_uncapped int,
is_char_uncapped_override int,
is_hide_rating int,
song_id text,
difficulty int,
score int,
shiny_perfect_count int,
perfect_count int,
near_count int,
miss_count int,
health int,
modifier int,
time_played int,
clear_type int,
rating real,
favorite_character int,
max_stamina_notification_enabled int,
current_map text
);''')
c.execute('''create table if not exists login(access_token text,
user_id int,
last_login_time int,
last_login_ip text,
last_login_device text
);''')
c.execute('''create table if not exists friend(user_id_me int,
user_id_other int,
primary key (user_id_me, user_id_other)
);''')
c.execute('''create table if not exists best_score(user_id int,
song_id text,
difficulty int,
score int,
shiny_perfect_count int,
perfect_count int,
near_count int,
miss_count int,
health int,
modifier int,
time_played int,
best_clear_type int,
clear_type int,
rating real,
primary key(user_id, song_id, difficulty)
);''')
c.execute('''create table if not exists user_char(user_id int,
character_id int,
level int,
exp real,
level_exp real,
frag real,
prog real,
overdrive real,
skill_id text,
skill_unlock_level int,
skill_requires_uncap int,
skill_id_uncap text,
char_type int,
is_uncapped int,
is_uncapped_override int,
primary key(user_id, character_id)
);''')
c.execute('''create table if not exists character(character_id int primary key,
name text,
level int,
exp real,
level_exp real,
frag real,
prog real,
overdrive real,
skill_id text,
skill_unlock_level int,
skill_requires_uncap int,
skill_id_uncap text,
char_type int,
uncap_cores text,
is_uncapped int,
is_uncapped_override int
);''')
c.execute('''create table if not exists recent30(user_id int primary key,
r0 real,
song_id0 text,
r1 real,
song_id1 text,
r2 real,
song_id2 text,
r3 real,
song_id3 text,
r4 real,
song_id4 text,
r5 real,
song_id5 text,
r6 real,
song_id6 text,
r7 real,
song_id7 text,
r8 real,
song_id8 text,
r9 real,
song_id9 text,
r10 real,
song_id10 text,
r11 real,
song_id11 text,
r12 real,
song_id12 text,
r13 real,
song_id13 text,
r14 real,
song_id14 text,
r15 real,
song_id15 text,
r16 real,
song_id16 text,
r17 real,
song_id17 text,
r18 real,
song_id18 text,
r19 real,
song_id19 text,
r20 real,
song_id20 text,
r21 real,
song_id21 text,
r22 real,
song_id22 text,
r23 real,
song_id23 text,
r24 real,
song_id24 text,
r25 real,
song_id25 text,
r26 real,
song_id26 text,
r27 real,
song_id27 text,
r28 real,
song_id28 text,
r29 real,
song_id29 text
);''')
c.execute('''create table if not exists user_world(user_id int,
map_id text,
curr_position int,
curr_capture real,
is_locked int,
primary key(user_id, map_id)
);''')
c.execute('''create table if not exists world_songplay(user_id int,
song_id text,
difficulty int,
stamina_multiply int,
fragment_multiply int,
prog_boost_multiply int,
primary key(user_id, song_id, difficulty)
);''')
char = ['Hikari','Tairitsu','Kou','Sapphire','Lethe','','Tairitsu(Axium)'
,'Tairitsu(Grievous Lady)','Stella','Hikari & Fisica','Ilith','Eto','Luna'
,'Shirabe','Hikari(Zero)','Hikari(Fracture)','Hikari(Summer)','Tairitsu(Summer)'
,'Tairitsu&Trin','Ayu','Eto&Luna','Yume','Seine & Hikari','Saya','Tairitsu & Chuni Penguin'
,'Chuni Penguin','Haruna','Nono','MTA-XXX','MDA-21','Kanae','Hikari(Fantasia)','Tairitsu(Sonata)','Sia','DORO*C'
,'Tairitsu(Tempest)','Brillante','Ilith(Summer)']
for i in range(0, 38):
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
sql = 'insert into character values('+str(i)+',"'+char[i]+'''",30,25000,25000,90,90,90,'',0,0,'',0,'',1,1)'''
c.execute(sql)
else:
if i != 5:
sql = 'insert into character values('+str(i)+',"'+char[i]+'''",30,25000,25000,90,90,90,'',0,0,'',0,'',0,0)'''
c.execute(sql)
conn.commit()
conn.close()
def arc_register(name: str, password: str):
def build_user_code(c):
return '123456789'
def build_user_id(c):
return 2000000
## def insert_user_char(c, user_id):
## for i in range(0, 38):
## if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
## sql = 'insert into user_char values('+str(user_id)+','+str(
## i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
## c.execute(sql)
## else:
## if i != 5:
## sql = 'insert into user_char values('+str(user_id)+','+str(
## i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
## c.execute(sql)
def insert_user_char(c, user_id):
# 为用户添加所有可用角色
c.execute('''select * from character''')
x = c.fetchall()
if x != []:
for i in x:
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
conn = sqlite3.connect('arcaea_database.db')
c = conn.cursor()
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
c.execute(
'''select exists(select * from user where name = :name)''', {'name': name})
if c.fetchone() == (0,):
user_code = build_user_code(c)
user_id = build_user_id(c)
now = int(time.time() * 1000)
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map)
values(:user_id, :name, :password, :join_date, :user_code, 1250, 1, 0, 1, 0, 0, -1, 0, '')
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd})
c.execute('''insert into recent30(user_id) values(:user_id)''', {
'user_id': user_id})
c.execute('''insert into best_score values(2000000,'vexaria',3,10000000,100,0,0,0,100,0,1599667200,3,3,10.8)''')
insert_user_char(c, user_id)
conn.commit()
conn.close()
return None
else:
conn.commit()
conn.close()
return None
arc_register('admin', 'admin123')

View File

@@ -0,0 +1,51 @@
{
"map_id": "byd_dement",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "dement2",
"require_type": "chart_unlock",
"coordinate": "-400,-650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 250,
"character_affinity": [13, 1],
"affinity_multiplier": [2.6, 1.6],
"step_count": 4,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_dement",
"position": 0,
"capture": 100.2865329512894
}, {
"map_id": "byd_dement",
"position": 1,
"capture": 110.31518624641834,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_dement",
"position": 2,
"capture": 39.39828080229226,
"items": [{
"type": "fragment",
"amount": 1200
}]
}, {
"map_id": "byd_dement",
"position": 3,
"capture": 0,
"items": [{
"id": "dement3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,45 @@
{
"map_id": "byd_fairytale",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "fairytale2",
"require_type": "chart_unlock",
"coordinate": "400,650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 200,
"character_affinity": [0, 1],
"affinity_multiplier": [2.5, 1.5],
"step_count": 3,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_fairytale",
"position": 0,
"capture": 100,
"step_type": ["speedlimit"],
"speed_limit_value": 65
}, {
"map_id": "byd_fairytale",
"position": 1,
"capture": 100,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 4
}]
}, {
"map_id": "byd_fairytale",
"position": 2,
"capture": 0,
"items": [{
"id": "fairytale3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,68 @@
{
"map_id": "byd_goodtek",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "goodtek2",
"require_type": "chart_unlock",
"coordinate": "900,650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 250,
"character_affinity": [0, 1],
"affinity_multiplier": [2.5, 1.5],
"step_count": 6,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_goodtek",
"position": 0,
"capture": 50
}, {
"map_id": "byd_goodtek",
"position": 1,
"capture": 50,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_goodtek",
"position": 2,
"capture": 50,
"items": [{
"type": "fragment",
"amount": 250
}]
}, {
"map_id": "byd_goodtek",
"position": 3,
"capture": 50,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_goodtek",
"position": 4,
"capture": 50,
"items": [{
"type": "fragment",
"amount": 275
}]
}, {
"map_id": "byd_goodtek",
"position": 5,
"capture": 0,
"items": [{
"id": "goodtek3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,91 @@
{
"map_id": "byd_infinityheaven",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "infinityheaven2",
"require_type": "chart_unlock",
"coordinate": "650,900",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 200,
"character_affinity": [0, 1],
"affinity_multiplier": [2.5, 1.5],
"step_count": 9,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_infinityheaven",
"position": 0,
"capture": 25
}, {
"map_id": "byd_infinityheaven",
"position": 1,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 2,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 3,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 4,
"capture": 25,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 2
}]
}, {
"map_id": "byd_infinityheaven",
"position": 5,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 6,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 7,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"map_id": "byd_infinityheaven",
"position": 8,
"capture": 0,
"items": [{
"id": "infinityheaven3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,61 @@
{
"map_id": "byd_purgatorium",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "purgatorium2",
"require_type": "chart_unlock",
"coordinate": "-900,-650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 200,
"character_affinity": [13, 1],
"affinity_multiplier": [2.6, 1.6],
"step_count": 5,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_purgatorium",
"position": 0,
"capture": 75
}, {
"map_id": "byd_purgatorium",
"position": 1,
"capture": 25,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_purgatorium",
"position": 2,
"capture": 25,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_purgatorium",
"position": 3,
"capture": 75,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"map_id": "byd_purgatorium",
"position": 4,
"capture": 0,
"items": [{
"id": "purgatorium3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,42 @@
{
"map_id": "byd_vexaria",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "vexaria2",
"require_type": "chart_unlock",
"coordinate": "650,400",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 150,
"character_affinity": [0, 1],
"affinity_multiplier": [2.5, 1.5],
"step_count": 3,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"map_id": "byd_vexaria",
"position": 0,
"capture": 140
}, {
"map_id": "byd_vexaria",
"position": 1,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 616
}]
}, {
"map_id": "byd_vexaria",
"position": 2,
"capture": 0,
"items": [{
"id": "vexaria3",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,428 @@
{
"map_id": "chapter3_conflict",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 3,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"coordinate": "-360,0",
"step_count": 85,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 10
}, {
"position": 2,
"capture": 10
}, {
"position": 3,
"capture": 10
}, {
"position": 4,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 5,
"capture": 1,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 6,
"capture": 1
}, {
"position": 7,
"capture": 1,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 8,
"capture": 1,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 9,
"capture": 1
}, {
"position": 10,
"capture": 20,
"items": [{
"type": "fragment",
"amount": 10
}]
}, {
"position": 11,
"capture": 20
}, {
"position": 12,
"capture": 20
}, {
"position": 13,
"capture": 20
}, {
"position": 14,
"capture": 20,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 15,
"capture": 2,
"items": [{
"type": "fragment",
"amount": 100
}]
}, {
"position": 16,
"capture": 2
}, {
"position": 17,
"capture": 2,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 18,
"capture": 2,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 19,
"capture": 2,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 20,
"capture": 30,
"items": [{
"type": "fragment",
"amount": 15
}]
}, {
"position": 21,
"capture": 30
}, {
"position": 22,
"capture": 30
}, {
"position": 23,
"capture": 30
}, {
"position": 24,
"capture": 30,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 25,
"capture": 3,
"items": [{
"type": "fragment",
"amount": 150
}]
}, {
"position": 26,
"capture": 3
}, {
"position": 27,
"capture": 3,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 28,
"capture": 3,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 29,
"capture": 3
}, {
"position": 30,
"capture": 40,
"items": [{
"id": "bookmaker",
"type": "world_song"
}]
}, {
"position": 31,
"capture": 40
}, {
"position": 32,
"capture": 40
}, {
"position": 33,
"capture": 40
}, {
"position": 34,
"capture": 40,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 35,
"capture": 4,
"items": [{
"type": "fragment",
"amount": 200
}]
}, {
"position": 36,
"capture": 4
}, {
"position": 37,
"capture": 4,
"restrict_id": "bookmaker",
"restrict_type": "song_id"
}, {
"position": 38,
"capture": 4,
"restrict_id": "bookmaker",
"restrict_type": "song_id"
}, {
"position": 39,
"capture": 4,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 2
}]
}, {
"position": 40,
"capture": 50,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 41,
"capture": 50
}, {
"position": 42,
"capture": 50
}, {
"position": 43,
"capture": 50
}, {
"position": 44,
"capture": 50,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 45,
"capture": 5,
"items": [{
"type": "fragment",
"amount": 250
}]
}, {
"position": 46,
"capture": 5
}, {
"position": 47,
"capture": 5,
"restrict_id": "bookmaker",
"restrict_type": "song_id"
}, {
"position": 48,
"capture": 5,
"restrict_id": "bookmaker",
"restrict_type": "song_id"
}, {
"position": 49,
"capture": 5,
"items": [{
"id": "darakunosono",
"type": "world_song"
}]
}, {
"position": 50,
"capture": 60,
"items": [{
"type": "fragment",
"amount": 30
}]
}, {
"position": 51,
"capture": 60
}, {
"position": 52,
"capture": 60
}, {
"position": 53,
"capture": 60
}, {
"position": 54,
"capture": 60,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 55,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 300
}]
}, {
"position": 56,
"capture": 6
}, {
"position": 57,
"capture": 6,
"restrict_id": "darakunosono",
"restrict_type": "song_id"
}, {
"position": 58,
"capture": 6,
"restrict_id": "darakunosono",
"restrict_type": "song_id"
}, {
"position": 59,
"capture": 6,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 3
}]
}, {
"position": 60,
"capture": 70,
"items": [{
"type": "fragment",
"amount": 40
}]
}, {
"position": 61,
"capture": 70
}, {
"position": 62,
"capture": 70,
"items": [{
"id": "espebranch",
"type": "world_song"
}]
}, {
"position": 63,
"capture": 70
}, {
"position": 64,
"capture": 70,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 65,
"capture": 8
}, {
"position": 66,
"capture": 8,
"restrict_id": "suomi",
"restrict_type": "song_id"
}, {
"position": 67,
"capture": 8,
"restrict_id": "suomi",
"restrict_type": "song_id"
}, {
"position": 68,
"capture": 8,
"restrict_id": "suomi",
"restrict_type": "song_id"
}, {
"position": 69,
"capture": 8,
"restrict_id": "suomi",
"restrict_type": "song_id"
}, {
"position": 70,
"capture": 80,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}, {
"position": 71,
"capture": 80
}, {
"position": 72,
"capture": 80
}, {
"position": 73,
"capture": 80
}, {
"position": 74,
"capture": 80,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 75,
"capture": 9,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}, {
"position": 76,
"capture": 9,
"restrict_id": "rugie",
"restrict_type": "song_id"
}, {
"position": 77,
"capture": 9,
"restrict_id": "rugie",
"restrict_type": "song_id"
}, {
"position": 78,
"capture": 9,
"restrict_id": "rugie",
"restrict_type": "song_id"
}, {
"position": 79,
"capture": 9,
"restrict_id": "rugie",
"restrict_type": "song_id"
}, {
"position": 80,
"capture": 90
}, {
"position": 81,
"capture": 90
}, {
"position": 82,
"capture": 90
}, {
"position": 83,
"capture": 90
}, {
"position": 84,
"capture": 0,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,268 @@
{
"map_id": "chapter3_conflict_2",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 3,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"coordinate": "-240,-180",
"step_count": 51,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 2,
"capture": 10
}, {
"position": 3,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 4,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 5,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 6,
"capture": 10
}, {
"position": 7,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 8,
"capture": 10
}, {
"position": 9,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 10,
"capture": 10
}, {
"position": 11,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 12,
"capture": 10
}, {
"position": 13,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 14,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 15,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 16,
"capture": 10
}, {
"position": 17,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 18,
"capture": 10
}, {
"position": 19,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 20,
"capture": 10
}, {
"position": 21,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 22,
"capture": 10
}, {
"position": 23,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 24,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 25,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 26,
"capture": 10
}, {
"position": 27,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 28,
"capture": 10
}, {
"position": 29,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 30,
"capture": 10
}, {
"position": 31,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 32,
"capture": 10
}, {
"position": 33,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 34,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 35,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 36,
"capture": 10
}, {
"position": 37,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 38,
"capture": 10
}, {
"position": 39,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 40,
"capture": 10,
"items": [{
"id": "nhelv",
"type": "world_song"
}]
}, {
"position": 41,
"capture": 100
}, {
"position": 42,
"capture": 100
}, {
"position": 43,
"capture": 100,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 44,
"capture": 100
}, {
"position": 45,
"capture": 100,
"items": [{
"type": "core",
"id": "core_ambivalent",
"amount": 5
}]
}, {
"position": 46,
"capture": 100
}, {
"position": 47,
"capture": 100,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 48,
"capture": 100
}, {
"position": 49,
"capture": 20,
"restrict_id": "nhelv",
"restrict_type": "song_id"
}, {
"position": 50,
"capture": 0,
"items": [{
"type": "core",
"id": "core_ambivalent",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,236 @@
{
"map_id": "chapter4_ripples",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 4,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"coordinate": "-280,-200",
"step_count": 51,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 13
}, {
"position": 1,
"capture": 14
}, {
"position": 2,
"capture": 15
}, {
"position": 3,
"capture": 16
}, {
"position": 4,
"capture": 17,
"items": [{
"type": "fragment",
"amount": 170
}]
}, {
"position": 5,
"capture": 16,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 6,
"capture": 15,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 7,
"capture": 14,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 8,
"capture": 13
}, {
"position": 9,
"capture": 14
}, {
"position": 10,
"capture": 15
}, {
"position": 11,
"capture": 16
}, {
"position": 12,
"capture": 17,
"items": [{
"type": "fragment",
"amount": 170
}]
}, {
"position": 13,
"capture": 16,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 14,
"capture": 15,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 15,
"capture": 14,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 16,
"capture": 13,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 17,
"capture": 14
}, {
"position": 18,
"capture": 15
}, {
"position": 19,
"capture": 16
}, {
"position": 20,
"capture": 17,
"items": [{
"id": "grimheart",
"type": "world_song"
}]
}, {
"position": 21,
"capture": 16
}, {
"position": 22,
"capture": 15
}, {
"position": 23,
"capture": 16
}, {
"position": 24,
"capture": 17
}, {
"position": 25,
"capture": 18
}, {
"position": 26,
"capture": 19,
"items": [{
"type": "fragment",
"amount": 190
}]
}, {
"position": 27,
"capture": 18,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 28,
"capture": 17,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 29,
"capture": 16,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 30,
"capture": 15
}, {
"position": 31,
"capture": 16
}, {
"position": 32,
"capture": 17
}, {
"position": 33,
"capture": 18
}, {
"position": 34,
"capture": 19,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 35,
"capture": 18
}, {
"position": 36,
"capture": 17
}, {
"position": 37,
"capture": 16
}, {
"position": 38,
"capture": 15
}, {
"position": 39,
"capture": 16
}, {
"position": 40,
"capture": 17
}, {
"position": 41,
"capture": 18
}, {
"position": 42,
"capture": 19,
"items": [{
"type": "fragment",
"amount": 190
}]
}, {
"position": 43,
"capture": 18,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 44,
"capture": 17,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 45,
"capture": 16,
"restrict_id": "grimheart",
"restrict_type": "song_id"
}, {
"position": 46,
"capture": 15,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 47,
"capture": 16
}, {
"position": 48,
"capture": 17
}, {
"position": 49,
"capture": 18
}, {
"position": 50,
"capture": 0,
"items": [{
"id": "vector",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,776 @@
{
"map_id": "chapter4_the_calm",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 4,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"coordinate": "-380,-30",
"step_count": 146,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 10
}]
}, {
"position": 2,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 10
}]
}, {
"position": 3,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 10
}]
}, {
"position": 4,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 10
}]
}, {
"position": 5,
"capture": 10
}, {
"position": 6,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 7,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 8,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 9,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 10,
"capture": 11
}, {
"position": 11,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 15
}]
}, {
"position": 12,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 15
}]
}, {
"position": 13,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 15
}]
}, {
"position": 14,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 15
}]
}, {
"position": 15,
"capture": 11
}, {
"position": 16,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 17,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 18,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 19,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 20,
"capture": 12
}, {
"position": 21,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 20
}]
}, {
"position": 22,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 20
}]
}, {
"position": 23,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 20
}]
}, {
"position": 24,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 20
}]
}, {
"position": 25,
"capture": 12
}, {
"position": 26,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 27,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 28,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 29,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 30,
"capture": 13
}, {
"position": 31,
"capture": 13,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 32,
"capture": 13,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 33,
"capture": 13,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 34,
"capture": 13,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 35,
"capture": 13
}, {
"position": 36,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 37,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 38,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 39,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 40,
"capture": 14
}, {
"position": 41,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 30
}]
}, {
"position": 42,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 30
}]
}, {
"position": 43,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 30
}]
}, {
"position": 44,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 30
}]
}, {
"position": 45,
"capture": 14
}, {
"position": 46,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 47,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 48,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 49,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 50,
"capture": 15
}, {
"position": 51,
"capture": 15,
"items": [{
"type": "fragment",
"amount": 35
}]
}, {
"position": 52,
"capture": 15,
"items": [{
"type": "fragment",
"amount": 35
}]
}, {
"position": 53,
"capture": 15,
"items": [{
"type": "fragment",
"amount": 35
}]
}, {
"position": 54,
"capture": 15,
"items": [{
"id": "diode",
"type": "world_song"
}]
}, {
"position": 55,
"capture": 15
}, {
"position": 56,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 57,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 58,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 59,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 60,
"capture": 16
}, {
"position": 61,
"capture": 16,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 62,
"capture": 16,
"items": [{
"type": "fragment",
"amount": 40
}]
}, {
"position": 63,
"capture": 16,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 64,
"capture": 16,
"items": [{
"type": "fragment",
"amount": 40
}]
}, {
"position": 65,
"capture": 16
}, {
"position": 66,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 67,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 68,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 69,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 70,
"capture": 17
}, {
"position": 71,
"capture": 17,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 72,
"capture": 17,
"items": [{
"type": "fragment",
"amount": 45
}]
}, {
"position": 73,
"capture": 17,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 74,
"capture": 17,
"items": [{
"type": "fragment",
"amount": 45
}]
}, {
"position": 75,
"capture": 17
}, {
"position": 76,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 77,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 78,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 79,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 80,
"capture": 18
}, {
"position": 81,
"capture": 18,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 82,
"capture": 18,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 83,
"capture": 18,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 84,
"capture": 18,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 85,
"capture": 18
}, {
"position": 86,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 87,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 88,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 89,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 90,
"capture": 19
}, {
"position": 91,
"capture": 19,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 92,
"capture": 19,
"items": [{
"type": "fragment",
"amount": 55
}]
}, {
"position": 93,
"capture": 19,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 94,
"capture": 19,
"items": [{
"id": "freefall",
"type": "world_song"
}]
}, {
"position": 95,
"capture": 19
}, {
"position": 96,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 97,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 98,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 99,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 100,
"capture": 20
}, {
"position": 101,
"capture": 20,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 102,
"capture": 20,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 103,
"capture": 20,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 104,
"capture": 20,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 105,
"capture": 20
}, {
"position": 106,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 107,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 108,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 109,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 110,
"capture": 21
}, {
"position": 111,
"capture": 21,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 112,
"capture": 21,
"items": [{
"type": "fragment",
"amount": 65
}]
}, {
"position": 113,
"capture": 21,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 114,
"capture": 21,
"items": [{
"type": "fragment",
"amount": 65
}]
}, {
"position": 115,
"capture": 21
}, {
"position": 116,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 117,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 118,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 119,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 120,
"capture": 22
}, {
"position": 121,
"capture": 22,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 122,
"capture": 22,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 123,
"capture": 22,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 124,
"capture": 22,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 125,
"capture": 22
}, {
"position": 126,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 127,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 128,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 129,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 130,
"capture": 23
}, {
"position": 131,
"capture": 23,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 132,
"capture": 23,
"items": [{
"type": "fragment",
"amount": 75
}]
}, {
"position": 133,
"capture": 23,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 134,
"capture": 23,
"items": [{
"id": "monochromeprincess",
"type": "world_song"
}]
}, {
"position": 135,
"capture": 23
}, {
"position": 136,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 137,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 138,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 139,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 140,
"capture": 24
}, {
"position": 141,
"capture": 24,
"restrict_id": "diode",
"restrict_type": "song_id"
}, {
"position": 142,
"capture": 24,
"restrict_id": "freefall",
"restrict_type": "song_id"
}, {
"position": 143,
"capture": 24,
"restrict_id": "monochromeprincess",
"restrict_type": "song_id"
}, {
"position": 144,
"capture": 24
}, {
"position": 145,
"capture": 0,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 3
}]
}]
}

View File

@@ -0,0 +1,199 @@
{
"map_id": "chapter4_waves",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 4,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"coordinate": "-480,-200",
"step_count": 41,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 11
}, {
"position": 2,
"capture": 13
}, {
"position": 3,
"capture": 16
}, {
"position": 4,
"capture": 20
}, {
"position": 5,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 150
}]
}, {
"position": 6,
"capture": 20,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 7,
"capture": 16,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 8,
"capture": 13,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 9,
"capture": 11
}, {
"position": 10,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 11,
"capture": 11
}, {
"position": 12,
"capture": 13
}, {
"position": 13,
"capture": 16
}, {
"position": 14,
"capture": 20
}, {
"position": 15,
"capture": 25,
"items": [{
"type": "fragment",
"amount": 150
}]
}, {
"position": 16,
"capture": 20,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 17,
"capture": 16,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 18,
"capture": 13,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 19,
"capture": 11
}, {
"position": 20,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 21,
"capture": 11
}, {
"position": 22,
"capture": 13
}, {
"position": 23,
"capture": 16
}, {
"position": 24,
"capture": 20
}, {
"position": 25,
"capture": 25,
"items": [{
"id": "revixy",
"type": "world_song"
}]
}, {
"position": 26,
"capture": 26
}, {
"position": 27,
"capture": 28
}, {
"position": 28,
"capture": 31
}, {
"position": 29,
"capture": 35
}, {
"position": 30,
"capture": 40,
"items": [{
"type": "fragment",
"amount": 400
}]
}, {
"position": 31,
"capture": 35,
"restrict_id": "revixy",
"restrict_type": "song_id"
}, {
"position": 32,
"capture": 31,
"restrict_id": "revixy",
"restrict_type": "song_id"
}, {
"position": 33,
"capture": 28,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 34,
"capture": 26
}, {
"position": 35,
"capture": 25,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 36,
"capture": 26
}, {
"position": 37,
"capture": 28
}, {
"position": 38,
"capture": 31
}, {
"position": 39,
"capture": 35
}, {
"position": 40,
"capture": 0,
"items": [{
"id": "supernova",
"type": "world_song"
}]
}]
}

View File

@@ -0,0 +1,477 @@
{
"map_id": "extra_originals",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 2,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "",
"require_value": 1,
"coordinate": "0,-200",
"step_count": 101,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 2
}, {
"position": 1,
"capture": 3
}, {
"position": 2,
"capture": 4
}, {
"position": 3,
"capture": 5
}, {
"position": 4,
"capture": 6,
"restrict_id": "infinityheaven",
"restrict_type": "song_id"
}, {
"position": 5,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 6,
"capture": 8
}, {
"position": 7,
"capture": 9
}, {
"position": 8,
"capture": 10
}, {
"position": 9,
"capture": 11,
"restrict_id": "infinityheaven",
"restrict_type": "song_id"
}, {
"position": 10,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 11,
"capture": 13
}, {
"position": 12,
"capture": 14
}, {
"position": 13,
"capture": 15
}, {
"position": 14,
"capture": 16,
"restrict_id": "infinityheaven",
"restrict_type": "song_id"
}, {
"position": 15,
"capture": 17,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 16,
"capture": 16,
"restrict_id": "reinvent",
"restrict_type": "song_id"
}, {
"position": 17,
"capture": 15
}, {
"position": 18,
"capture": 14
}, {
"position": 19,
"capture": 13
}, {
"position": 20,
"capture": 12,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 21,
"capture": 11,
"restrict_id": "reinvent",
"restrict_type": "song_id"
}, {
"position": 22,
"capture": 10
}, {
"position": 23,
"capture": 9
}, {
"position": 24,
"capture": 8
}, {
"position": 25,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 26,
"capture": 6,
"restrict_id": "reinvent",
"restrict_type": "song_id"
}, {
"position": 27,
"capture": 5
}, {
"position": 28,
"capture": 4
}, {
"position": 29,
"capture": 3,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 30,
"capture": 4,
"items": [{
"id": "syro",
"type": "world_song"
}]
}, {
"position": 31,
"capture": 5,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 32,
"capture": 6
}, {
"position": 33,
"capture": 7
}, {
"position": 34,
"capture": 8,
"restrict_id": "dement",
"restrict_type": "song_id"
}, {
"position": 35,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 36,
"capture": 10
}, {
"position": 37,
"capture": 11
}, {
"position": 38,
"capture": 12
}, {
"position": 39,
"capture": 13,
"restrict_id": "dement",
"restrict_type": "song_id"
}, {
"position": 40,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 41,
"capture": 15
}, {
"position": 42,
"capture": 16
}, {
"position": 43,
"capture": 17
}, {
"position": 44,
"capture": 18,
"restrict_id": "dement",
"restrict_type": "song_id"
}, {
"position": 45,
"capture": 19,
"items": [{
"type": "fragment",
"amount": 80
}]
}, {
"position": 46,
"capture": 18,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 47,
"capture": 17
}, {
"position": 48,
"capture": 16
}, {
"position": 49,
"capture": 15
}, {
"position": 50,
"capture": 14,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 51,
"capture": 13,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 52,
"capture": 12
}, {
"position": 53,
"capture": 11
}, {
"position": 54,
"capture": 10
}, {
"position": 55,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 60
}]
}, {
"position": 56,
"capture": 8,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 57,
"capture": 7
}, {
"position": 58,
"capture": 6
}, {
"position": 59,
"capture": 5,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 60,
"capture": 6,
"items": [{
"id": "blaster",
"type": "world_song"
}]
}, {
"position": 61,
"capture": 7,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 62,
"capture": 8
}, {
"position": 63,
"capture": 9
}, {
"position": 64,
"capture": 10,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 65,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 66,
"capture": 12
}, {
"position": 67,
"capture": 13
}, {
"position": 68,
"capture": 14
}, {
"position": 69,
"capture": 15,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 70,
"capture": 16,
"items": [{
"type": "fragment",
"amount": 80
}]
}, {
"position": 71,
"capture": 17
}, {
"position": 72,
"capture": 18
}, {
"position": 73,
"capture": 19
}, {
"position": 74,
"capture": 20,
"restrict_id": "syro",
"restrict_type": "song_id"
}, {
"position": 75,
"capture": 21,
"items": [{
"type": "fragment",
"amount": 90
}]
}, {
"position": 76,
"capture": 22
}, {
"position": 77,
"capture": 23
}, {
"position": 78,
"capture": 23
}, {
"position": 79,
"capture": 22
}, {
"position": 80,
"capture": 21,
"items": [{
"type": "fragment",
"amount": 90
}]
}, {
"position": 81,
"capture": 20,
"restrict_id": "blaster",
"restrict_type": "song_id"
}, {
"position": 82,
"capture": 19
}, {
"position": 83,
"capture": 18
}, {
"position": 84,
"capture": 17
}, {
"position": 85,
"capture": 16,
"items": [{
"type": "fragment",
"amount": 80
}]
}, {
"position": 86,
"capture": 15,
"restrict_id": "blaster",
"restrict_type": "song_id"
}, {
"position": 87,
"capture": 14
}, {
"position": 88,
"capture": 13
}, {
"position": 89,
"capture": 12
}, {
"position": 90,
"capture": 11,
"items": [{
"type": "fragment",
"amount": 70
}]
}, {
"position": 91,
"capture": 10,
"restrict_id": "blaster",
"restrict_type": "song_id"
}, {
"position": 92,
"capture": 9
}, {
"position": 93,
"capture": 8
}, {
"position": 94,
"capture": 7,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 95,
"capture": 8,
"items": [{
"id": "cyberneciacatharsis",
"type": "world_song"
}]
}, {
"position": 96,
"capture": 400
}, {
"position": 97,
"capture": 2,
"step_type": ["plusstamina"],
"plus_stamina_value": 6
}, {
"position": 98,
"capture": 450,
"items": [{
"type": "core",
"id": "core_crimson",
"amount": 5
}]
}, {
"position": 99,
"capture": 1,
"step_type": ["plusstamina"],
"plus_stamina_value": 6
}, {
"position": 100,
"capture": 0,
"items": [{
"type": "core",
"id": "core_crimson",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,407 @@
{
"map_id": "hikari_art",
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 1,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "",
"require_value": 1,
"is_legacy": true,
"stamina_cost": 1,
"coordinate": "-270,150",
"step_count": 91,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 5
}, {
"position": 1,
"capture": 5
}, {
"position": 2,
"capture": 5
}, {
"position": 3,
"capture": 5
}, {
"position": 4,
"capture": 5
}, {
"position": 5,
"capture": 6,
"items": [{
"id": "babaroque",
"type": "world_song"
}]
}, {
"position": 6,
"capture": 6
}, {
"position": 7,
"capture": 6
}, {
"position": 8,
"capture": 6
}, {
"position": 9,
"capture": 6
}, {
"position": 10,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 11,
"capture": 6
}, {
"position": 12,
"capture": 6
}, {
"position": 13,
"capture": 6,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 14,
"capture": 6,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 15,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 16,
"capture": 6
}, {
"position": 17,
"capture": 6
}, {
"position": 18,
"capture": 6
}, {
"position": 19,
"capture": 6
}, {
"position": 20,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 21,
"capture": 6
}, {
"position": 22,
"capture": 6
}, {
"position": 23,
"capture": 6
}, {
"position": 24,
"capture": 6
}, {
"position": 25,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 26,
"capture": 6
}, {
"position": 27,
"capture": 6,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 28,
"capture": 6,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 29,
"capture": 6,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 30,
"capture": 7,
"items": [{
"id": "shadesoflight",
"type": "world_song"
}]
}, {
"position": 31,
"capture": 7
}, {
"position": 32,
"capture": 7
}, {
"position": 33,
"capture": 7
}, {
"position": 34,
"capture": 7
}, {
"position": 35,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 36,
"capture": 7
}, {
"position": 37,
"capture": 7
}, {
"position": 38,
"capture": 7
}, {
"position": 39,
"capture": 7
}, {
"position": 40,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 41,
"capture": 7
}, {
"position": 42,
"capture": 7
}, {
"position": 43,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 44,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 45,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 46,
"capture": 7
}, {
"position": 47,
"capture": 7
}, {
"position": 48,
"capture": 7
}, {
"position": 49,
"capture": 7
}, {
"position": 50,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 51,
"capture": 7
}, {
"position": 52,
"capture": 7
}, {
"position": 53,
"capture": 7
}, {
"position": 54,
"capture": 7
}, {
"position": 55,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 56,
"capture": 7
}, {
"position": 57,
"capture": 7
}, {
"position": 58,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 59,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 60,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 61,
"capture": 7
}, {
"position": 62,
"capture": 7
}, {
"position": 63,
"capture": 7
}, {
"position": 64,
"capture": 7
}, {
"position": 65,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 66,
"capture": 7
}, {
"position": 67,
"capture": 7
}, {
"position": 68,
"capture": 7
}, {
"position": 69,
"capture": 7
}, {
"position": 70,
"capture": 7,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 71,
"capture": 7,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 72,
"capture": 7,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 73,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 74,
"capture": 7,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 75,
"capture": 100,
"items": [{
"id": "kanagawa",
"type": "world_song"
}]
}, {
"position": 76,
"capture": 100
}, {
"position": 77,
"capture": 100
}, {
"position": 78,
"capture": 100
}, {
"position": 79,
"capture": 100,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 80,
"capture": 100,
"items": [{
"type": "core",
"id": "core_hollow",
"amount": 5
}]
}, {
"position": 81,
"capture": 150
}, {
"position": 82,
"capture": 150
}, {
"position": 83,
"capture": 150
}, {
"position": 84,
"capture": 150,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 85,
"capture": 150,
"items": [{
"type": "core",
"id": "core_hollow",
"amount": 5
}]
}, {
"position": 86,
"capture": 200
}, {
"position": 87,
"capture": 200
}, {
"position": 88,
"capture": 200
}, {
"position": 89,
"capture": 200,
"restrict_id": "ignotus",
"restrict_type": "song_id"
}, {
"position": 90,
"capture": 0,
"items": [{
"type": "core",
"id": "core_hollow",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,595 @@
{
"map_id": "hikari_happy",
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 1,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"is_legacy": true,
"stamina_cost": 1,
"coordinate": "270,150",
"step_count": 136,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 8
}, {
"position": 1,
"capture": 8
}, {
"position": 2,
"capture": 8
}, {
"position": 3,
"capture": 8
}, {
"position": 4,
"capture": 8
}, {
"position": 5,
"capture": 8,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 6,
"capture": 8
}, {
"position": 7,
"capture": 8
}, {
"position": 8,
"capture": 8
}, {
"position": 9,
"capture": 8
}, {
"position": 10,
"capture": 9,
"items": [{
"id": "harutopia",
"type": "world_song"
}]
}, {
"position": 11,
"capture": 9
}, {
"position": 12,
"capture": 9
}, {
"position": 13,
"capture": 9
}, {
"position": 14,
"capture": 9
}, {
"position": 15,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 16,
"capture": 9
}, {
"position": 17,
"capture": 9
}, {
"position": 18,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 19,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 20,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 21,
"capture": 9
}, {
"position": 22,
"capture": 9
}, {
"position": 23,
"capture": 9
}, {
"position": 24,
"capture": 9
}, {
"position": 25,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 26,
"capture": 9
}, {
"position": 27,
"capture": 9
}, {
"position": 28,
"capture": 9
}, {
"position": 29,
"capture": 9
}, {
"position": 30,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 31,
"capture": 9
}, {
"position": 32,
"capture": 9,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 33,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 34,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 35,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 36,
"capture": 9
}, {
"position": 37,
"capture": 9
}, {
"position": 38,
"capture": 9
}, {
"position": 39,
"capture": 9
}, {
"position": 40,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 41,
"capture": 9
}, {
"position": 42,
"capture": 9
}, {
"position": 43,
"capture": 9
}, {
"position": 44,
"capture": 9
}, {
"position": 45,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 46,
"capture": 9
}, {
"position": 47,
"capture": 9
}, {
"position": 48,
"capture": 9
}, {
"position": 49,
"capture": 9
}, {
"position": 50,
"capture": 9,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 51,
"capture": 9
}, {
"position": 52,
"capture": 9
}, {
"position": 53,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 54,
"capture": 9,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 55,
"capture": 10,
"items": [{
"id": "goodtek",
"type": "world_song"
}]
}, {
"position": 56,
"capture": 10
}, {
"position": 57,
"capture": 10
}, {
"position": 58,
"capture": 10
}, {
"position": 59,
"capture": 10
}, {
"position": 60,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 61,
"capture": 10
}, {
"position": 62,
"capture": 10
}, {
"position": 63,
"capture": 10
}, {
"position": 64,
"capture": 10
}, {
"position": 65,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 66,
"capture": 10
}, {
"position": 67,
"capture": 10
}, {
"position": 68,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 69,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 70,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 71,
"capture": 10
}, {
"position": 72,
"capture": 10
}, {
"position": 73,
"capture": 10
}, {
"position": 74,
"capture": 10
}, {
"position": 75,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 76,
"capture": 10
}, {
"position": 77,
"capture": 10
}, {
"position": 78,
"capture": 10
}, {
"position": 79,
"capture": 10
}, {
"position": 80,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 81,
"capture": 10
}, {
"position": 82,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 83,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 84,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 85,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 86,
"capture": 10
}, {
"position": 87,
"capture": 10
}, {
"position": 88,
"capture": 10
}, {
"position": 89,
"capture": 10
}, {
"position": 90,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 91,
"capture": 10
}, {
"position": 92,
"capture": 10
}, {
"position": 93,
"capture": 10
}, {
"position": 94,
"capture": 10
}, {
"position": 95,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 96,
"capture": 10
}, {
"position": 97,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 98,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 99,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 100,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 101,
"capture": 10
}, {
"position": 102,
"capture": 10
}, {
"position": 103,
"capture": 10
}, {
"position": 104,
"capture": 10
}, {
"position": 105,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 106,
"capture": 10
}, {
"position": 107,
"capture": 10
}, {
"position": 108,
"capture": 10
}, {
"position": 109,
"capture": 10
}, {
"position": 110,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 111,
"capture": 10
}, {
"position": 112,
"capture": 10
}, {
"position": 113,
"capture": 10
}, {
"position": 114,
"capture": 10
}, {
"position": 115,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 116,
"capture": 10
}, {
"position": 117,
"capture": 10
}, {
"position": 118,
"capture": 10
}, {
"position": 119,
"capture": 10
}, {
"position": 120,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 121,
"capture": 10,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 122,
"capture": 10,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 123,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 124,
"capture": 10,
"restrict_id": "goodtek",
"restrict_type": "song_id"
}, {
"position": 125,
"capture": 25,
"items": [{
"id": "dreaminattraction",
"type": "world_song"
}]
}, {
"position": 126,
"capture": 25
}, {
"position": 127,
"capture": 25
}, {
"position": 128,
"capture": 25
}, {
"position": 129,
"capture": 25
}, {
"position": 130,
"capture": 25,
"step_type": ["plusstamina"],
"plus_stamina_value": 4
}, {
"position": 131,
"capture": 25,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 132,
"capture": 25,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 133,
"capture": 25,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 134,
"capture": 25,
"restrict_id": "harutopia",
"restrict_type": "song_id"
}, {
"position": 135,
"capture": 0,
"items": [{
"type": "core",
"id": "core_hollow",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,595 @@
{
"map_id": "tairitsu_arcs",
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 1,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "fragment",
"require_value": 200,
"is_legacy": true,
"stamina_cost": 1,
"coordinate": "-270,-150",
"step_count": 136,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 8
}, {
"position": 1,
"capture": 8
}, {
"position": 2,
"capture": 8
}, {
"position": 3,
"capture": 8
}, {
"position": 4,
"capture": 8
}, {
"position": 5,
"capture": 8,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 6,
"capture": 8
}, {
"position": 7,
"capture": 8
}, {
"position": 8,
"capture": 8
}, {
"position": 9,
"capture": 8
}, {
"position": 10,
"capture": 9,
"items": [{
"id": "rabbitintheblackroom",
"type": "world_song"
}]
}, {
"position": 11,
"capture": 9
}, {
"position": 12,
"capture": 9
}, {
"position": 13,
"capture": 9
}, {
"position": 14,
"capture": 9
}, {
"position": 15,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 16,
"capture": 9
}, {
"position": 17,
"capture": 9
}, {
"position": 18,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 19,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 20,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 21,
"capture": 9
}, {
"position": 22,
"capture": 9
}, {
"position": 23,
"capture": 9
}, {
"position": 24,
"capture": 9
}, {
"position": 25,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 26,
"capture": 9
}, {
"position": 27,
"capture": 9
}, {
"position": 28,
"capture": 9
}, {
"position": 29,
"capture": 9
}, {
"position": 30,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 31,
"capture": 9
}, {
"position": 32,
"capture": 9,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 33,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 34,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 35,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 36,
"capture": 9
}, {
"position": 37,
"capture": 9
}, {
"position": 38,
"capture": 9
}, {
"position": 39,
"capture": 9
}, {
"position": 40,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 41,
"capture": 9
}, {
"position": 42,
"capture": 9
}, {
"position": 43,
"capture": 9
}, {
"position": 44,
"capture": 9
}, {
"position": 45,
"capture": 9,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 46,
"capture": 9
}, {
"position": 47,
"capture": 9
}, {
"position": 48,
"capture": 9
}, {
"position": 49,
"capture": 9
}, {
"position": 50,
"capture": 9,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 51,
"capture": 9
}, {
"position": 52,
"capture": 9
}, {
"position": 53,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 54,
"capture": 9,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 55,
"capture": 10,
"items": [{
"id": "qualia",
"type": "world_song"
}]
}, {
"position": 56,
"capture": 10
}, {
"position": 57,
"capture": 10
}, {
"position": 58,
"capture": 10
}, {
"position": 59,
"capture": 10
}, {
"position": 60,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 61,
"capture": 10
}, {
"position": 62,
"capture": 10
}, {
"position": 63,
"capture": 10
}, {
"position": 64,
"capture": 10
}, {
"position": 65,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 66,
"capture": 10
}, {
"position": 67,
"capture": 10
}, {
"position": 68,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 69,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 70,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 71,
"capture": 10
}, {
"position": 72,
"capture": 10
}, {
"position": 73,
"capture": 10
}, {
"position": 74,
"capture": 10
}, {
"position": 75,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 76,
"capture": 10
}, {
"position": 77,
"capture": 10
}, {
"position": 78,
"capture": 10
}, {
"position": 79,
"capture": 10
}, {
"position": 80,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 81,
"capture": 10
}, {
"position": 82,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 83,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 84,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 85,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 86,
"capture": 10
}, {
"position": 87,
"capture": 10
}, {
"position": 88,
"capture": 10
}, {
"position": 89,
"capture": 10
}, {
"position": 90,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 91,
"capture": 10
}, {
"position": 92,
"capture": 10
}, {
"position": 93,
"capture": 10
}, {
"position": 94,
"capture": 10
}, {
"position": 95,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 96,
"capture": 10
}, {
"position": 97,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 98,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 99,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 100,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 101,
"capture": 10
}, {
"position": 102,
"capture": 10
}, {
"position": 103,
"capture": 10
}, {
"position": 104,
"capture": 10
}, {
"position": 105,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 106,
"capture": 10
}, {
"position": 107,
"capture": 10
}, {
"position": 108,
"capture": 10
}, {
"position": 109,
"capture": 10
}, {
"position": 110,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 111,
"capture": 10
}, {
"position": 112,
"capture": 10
}, {
"position": 113,
"capture": 10
}, {
"position": 114,
"capture": 10
}, {
"position": 115,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 116,
"capture": 10
}, {
"position": 117,
"capture": 10
}, {
"position": 118,
"capture": 10
}, {
"position": 119,
"capture": 10
}, {
"position": 120,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 121,
"capture": 10,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 122,
"capture": 10,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 123,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 124,
"capture": 10,
"restrict_id": "qualia",
"restrict_type": "song_id"
}, {
"position": 125,
"capture": 25,
"items": [{
"id": "redandblue",
"type": "world_song"
}]
}, {
"position": 126,
"capture": 25
}, {
"position": 127,
"capture": 25
}, {
"position": 128,
"capture": 25
}, {
"position": 129,
"capture": 25
}, {
"position": 130,
"capture": 25,
"step_type": ["plusstamina"],
"plus_stamina_value": 4
}, {
"position": 131,
"capture": 25,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 132,
"capture": 25,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 133,
"capture": 25,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 134,
"capture": 25,
"restrict_id": "rabbitintheblackroom",
"restrict_type": "song_id"
}, {
"position": 135,
"capture": 0,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,407 @@
{
"map_id": "tairitsu_tech",
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 1,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": false,
"require_id": "",
"require_type": "",
"require_value": 1,
"is_legacy": true,
"stamina_cost": 1,
"coordinate": "270,-150",
"step_count": 91,
"custom_bg": "",
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 5
}, {
"position": 1,
"capture": 5
}, {
"position": 2,
"capture": 5
}, {
"position": 3,
"capture": 5
}, {
"position": 4,
"capture": 5
}, {
"position": 5,
"capture": 6,
"items": [{
"id": "lucifer",
"type": "world_song"
}]
}, {
"position": 6,
"capture": 6
}, {
"position": 7,
"capture": 6
}, {
"position": 8,
"capture": 6
}, {
"position": 9,
"capture": 6
}, {
"position": 10,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 11,
"capture": 6
}, {
"position": 12,
"capture": 6
}, {
"position": 13,
"capture": 6,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 14,
"capture": 6,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 15,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 16,
"capture": 6
}, {
"position": 17,
"capture": 6
}, {
"position": 18,
"capture": 6
}, {
"position": 19,
"capture": 6
}, {
"position": 20,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 21,
"capture": 6
}, {
"position": 22,
"capture": 6
}, {
"position": 23,
"capture": 6
}, {
"position": 24,
"capture": 6
}, {
"position": 25,
"capture": 6,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 26,
"capture": 6
}, {
"position": 27,
"capture": 6,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 28,
"capture": 6,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 29,
"capture": 6,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 30,
"capture": 7,
"items": [{
"id": "anokumene",
"type": "world_song"
}]
}, {
"position": 31,
"capture": 7
}, {
"position": 32,
"capture": 7
}, {
"position": 33,
"capture": 7
}, {
"position": 34,
"capture": 7
}, {
"position": 35,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 36,
"capture": 7
}, {
"position": 37,
"capture": 7
}, {
"position": 38,
"capture": 7
}, {
"position": 39,
"capture": 7
}, {
"position": 40,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 41,
"capture": 7
}, {
"position": 42,
"capture": 7
}, {
"position": 43,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 44,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 45,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 46,
"capture": 7
}, {
"position": 47,
"capture": 7
}, {
"position": 48,
"capture": 7
}, {
"position": 49,
"capture": 7
}, {
"position": 50,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 51,
"capture": 7
}, {
"position": 52,
"capture": 7
}, {
"position": 53,
"capture": 7
}, {
"position": 54,
"capture": 7
}, {
"position": 55,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 56,
"capture": 7
}, {
"position": 57,
"capture": 7
}, {
"position": 58,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 59,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 60,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 50
}]
}, {
"position": 61,
"capture": 7
}, {
"position": 62,
"capture": 7
}, {
"position": 63,
"capture": 7
}, {
"position": 64,
"capture": 7
}, {
"position": 65,
"capture": 7,
"items": [{
"type": "fragment",
"amount": 25
}]
}, {
"position": 66,
"capture": 7
}, {
"position": 67,
"capture": 7
}, {
"position": 68,
"capture": 7
}, {
"position": 69,
"capture": 7
}, {
"position": 70,
"capture": 7,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 71,
"capture": 7,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 72,
"capture": 7,
"restrict_id": "lucifer",
"restrict_type": "song_id"
}, {
"position": 73,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 74,
"capture": 7,
"restrict_id": "anokumene",
"restrict_type": "song_id"
}, {
"position": 75,
"capture": 100,
"items": [{
"id": "ignotus",
"type": "world_song"
}]
}, {
"position": 76,
"capture": 100
}, {
"position": 77,
"capture": 100
}, {
"position": 78,
"capture": 100
}, {
"position": 79,
"capture": 100,
"restrict_id": "babaroque",
"restrict_type": "song_id"
}, {
"position": 80,
"capture": 100,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}, {
"position": 81,
"capture": 150
}, {
"position": 82,
"capture": 150
}, {
"position": 83,
"capture": 150
}, {
"position": 84,
"capture": 150,
"restrict_id": "shadesoflight",
"restrict_type": "song_id"
}, {
"position": 85,
"capture": 150,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}, {
"position": 86,
"capture": 200
}, {
"position": 87,
"capture": 200
}, {
"position": 88,
"capture": 200
}, {
"position": 89,
"capture": 200,
"restrict_id": "kanagawa",
"restrict_type": "song_id"
}, {
"position": 90,
"capture": 0,
"items": [{
"type": "core",
"id": "core_desolate",
"amount": 5
}]
}]
}

View File

@@ -0,0 +1,94 @@
{
"map_id": "test",
"is_legacy": false,
"is_beyond": false,
"beyond_health": 200,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 0,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": true,
"require_id": "",
"require_type": "",
"require_value": 0,
"coordinate": "0,0",
"step_count": 12,
"custom_bg": "",
"stamina_cost": 2,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 20,
"items": [{
"type": "fragment",
"amount": 1000
}]
}, {
"position": 2,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id"
}, {
"position": 3,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"]
}, {
"position": 4,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}]
}, {
"position": 5,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 20
}, {
"position": 6,
"capture": 10
}, {
"position": 7,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2
}, {
"position": 8,
"capture": 10
}, {
"position": 9,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 10,
"capture": 10000,
"step_type": ["plusstamina","speedlimit"],
"plus_stamina_value": 2,
"speed_limit_value": 5,
"restrict_id": "fractureray",
"restrict_type": "song_id"
}, {
"position": 11,
"capture": 0,
"items": [{
"type": "core",
"id": "core_crimson",
"amount": 500
}, {
"type": "fragment",
"amount": 125
}]
}]
}

View File

@@ -0,0 +1,120 @@
{
"map_id": "test2",
"is_legacy": true,
"is_beyond": false,
"beyond_health": 100,
"character_affinity": [],
"affinity_multiplier": [],
"chapter": 0,
"available_from": -1,
"available_to": 2106124800000,
"is_repeatable": true,
"require_id": "",
"require_type": "",
"require_value": 0,
"coordinate": "200,200",
"step_count": 12,
"custom_bg": "",
"stamina_cost": 1,
"curr_position": 0,
"curr_capture": 0,
"is_locked": false,
"steps": [{
"position": 0,
"capture": 10
}, {
"position": 1,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 1000
}]
}, {
"position": 2,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 3,
"capture": 10,
"restrict_id": "base",
"restrict_type": "pack_id",
"step_type": ["randomsong"],
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 4,
"capture": 10,
"items": [{
"type": "core",
"id": "core_generic",
"amount": 1
}, {
"type": "fragment",
"amount": 125
}]
}, {
"position": 5,
"capture": 10,
"step_type": ["speedlimit"],
"speed_limit_value": 60,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 6,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 7,
"capture": 10,
"step_type": ["plusstamina"],
"plus_stamina_value": 2,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 8,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 9,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 10,
"capture": 10,
"items": [{
"type": "fragment",
"amount": 125
}]
}, {
"position": 11,
"capture": 0,
"items": [{
"type": "core",
"id": "core_crimson",
"amount": 50
}, {
"type": "fragment",
"amount": 125
}]
}]
}

553
v1.3/main.py Normal file
View File

@@ -0,0 +1,553 @@
from flask import Flask, request, jsonify, make_response
import configparser
import base64
import server.auth
import server.info
import server.setme
import server.arcscore
import web.login
import web.index
import server.arcworld
app = Flask(__name__)
wsgi_app = app.wsgi_app
def error_return(error_code): # 错误返回
# 100 无法在此ip地址下登录游戏
# 101 用户名占用
# 102 电子邮箱已注册
# 103 已有一个账号由此设备创建
# 104 用户名密码错误
# 105 24小时内登入两台设备
# 106 账户冻结
# 107 你没有足够的体力
# 401 用户不存在
# 403 无法连接至服务器
# 501 502 此物品目前无法获取
# 504 无效的序列码
# 505 此序列码已被使用
# 506 你已拥有了此物品
# 601 好友列表已满
# 602 此用户已是好友
# 604 你不能加自己为好友
# 其它 发生未知错误
return jsonify({
"success": False,
"error_code": error_code
})
@app.route('/')
def hello():
return "Hello World!"
@app.route('/coffee/12/auth/login', methods=['POST']) # 登录接口
def login():
headers = request.headers
id_pwd = headers['Authorization']
id_pwd = base64.b64decode(id_pwd[6:]).decode()
name, password = id_pwd.split(':', 1)
try:
token = server.auth.arc_login(name, password)
if token is not None:
r = {"success": True, "token_type": "Bearer"}
r['access_token'] = token
return jsonify(r)
else:
return error_return(104) # 用户名或密码错误
except:
return error_return(108)
@app.route('/coffee/12/user/', methods=['POST']) # 注册接口
def register():
name = request.form['name']
password = request.form['password']
try:
user_id, token, error_code = server.auth.arc_register(name, password)
if user_id is not None:
r = {"success": True, "value": {
'user_id': user_id, 'access_token': token}}
return jsonify(r)
else:
return error_return(error_code) # 应该是101用户名被占用毕竟电子邮箱、设备号没记录
except:
return error_return(108)
@app.route('/coffee/12/compose/aggregate', methods=['GET']) # 用户信息获取
def aggregate():
calls = request.args.get('calls')
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断我猜get的参数就两种
r = server.info.arc_aggregate_small(user_id)
else:
r = server.info.arc_aggregate_big(user_id)
return jsonify(r)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/user/me/character', methods=['POST']) # 角色切换
def character_change():
headers = request.headers
token = headers['Authorization']
token = token[7:]
character_id = request.form['character']
skill_sealed = request.form['skill_sealed']
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
flag = server.setme.change_char(
user_id, character_id, skill_sealed)
if flag:
return jsonify({
"success": True,
"value": {
"user_id": user_id,
"character": character_id
}
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/<path:path>/toggle_uncap', methods=['POST']) # 角色觉醒切换
def character_uncap(path):
character_id = int(path[22:])
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r = server.setme.change_char_uncap(user_id, character_id)
if r is not None:
return jsonify({
"success": True,
"value": {
"user_id": user_id,
"character": [r]
}
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/friend/me/add', methods=['POST']) # 加好友
def add_friend():
headers = request.headers
token = headers['Authorization']
token = token[7:]
friend_code = request.form['friend_code']
try:
user_id = server.auth.token_get_id(token)
friend_id = server.auth.code_get_id(friend_code)
if user_id is not None and friend_id is not None:
r = server.setme.arc_add_friend(user_id, friend_id)
if r is not None and r != 602 and r != 604:
return jsonify({
"success": True,
"value": {
"user_id": user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": r
}
})
else:
if r is not None:
return error_return(r)
else:
return error_return(108)
else:
if friend_id is None:
return error_return(401)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/friend/me/delete', methods=['POST']) # 删好友
def delete_friend():
headers = request.headers
token = headers['Authorization']
token = token[7:]
friend_id = int(request.form['friend_id'])
try:
user_id = server.auth.token_get_id(token)
if user_id is not None and friend_id is not None:
r = server.setme.arc_delete_friend(user_id, friend_id)
if r is not None:
return jsonify({
"success": True,
"value": {
"user_id": user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": r
}
})
else:
return error_return(108)
else:
if friend_id is None:
return error_return(401)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/score/song/friend', methods=['GET']) # 好友排名默认最多50
def song_score_friend():
song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty')
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r = server.arcscore.arc_score_friend(user_id, song_id, difficulty)
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/score/song/me', methods=['GET']) # 我的排名默认最多20
def song_score_me():
song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty')
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r = server.arcscore.arc_score_me(user_id, song_id, difficulty)
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/score/song', methods=['GET']) # TOP20
def song_score_top():
song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty')
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r = server.arcscore.arc_score_top(song_id, difficulty)
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/score/song', methods=['POST']) # 成绩上传
def song_score_post():
headers = request.headers
token = headers['Authorization']
token = token[7:]
song_id = request.form['song_id']
difficulty = int(request.form['difficulty'])
score = int(request.form['score'])
shiny_perfect_count = int(request.form['shiny_perfect_count'])
perfect_count = int(request.form['perfect_count'])
near_count = int(request.form['near_count'])
miss_count = int(request.form['miss_count'])
health = int(request.form['health'])
modifier = int(request.form['modifier'])
beyond_gauge = int(request.form['beyond_gauge'])
clear_type = int(request.form['clear_type'])
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r, re = server.arcscore.arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count,
perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type)
if r:
if re:
return jsonify({
"success": True,
"value": re
})
else:
return jsonify({
"success": True,
"value": {"user_rating": r}
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/score/token', methods=['GET']) # 成绩上传所需的token显然我不想验证
def score_token():
return jsonify({
"success": True,
"value": {
"token": "1145141919810"
}
})
# 世界模式成绩上传所需的token无验证
@app.route('/coffee/12/score/token/world', methods=['GET'])
def score_token_world():
headers = request.headers
token = headers['Authorization']
token = token[7:]
args = request.args
try:
user_id = server.auth.token_get_id(token)
if user_id:
server.arcworld.play_world_song(user_id, args)
return jsonify({
"success": True,
"value": {
"stamina": 12,
"max_stamina_ts": 1599547603825,
"token": "13145201919810"
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/user/me/save', methods=['GET']) # 从云端同步
def cloud_get():
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
r = server.arcscore.arc_all_get(user_id)
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/user/me/save', methods=['POST']) # 向云端同步
def cloud_post():
headers = request.headers
token = headers['Authorization']
token = token[7:]
scores_data = request.form['scores_data']
clearlamps_data = request.form['clearlamps_data']
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data)
return jsonify({
"success": True,
"value": {
"user_id": user_id
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/purchase/me/redeem', methods=['POST']) # 兑换码,自然没有用
def redeem():
return error_return(504)
# 购买自然没有用只是为了world模式boost一下
@app.route('/coffee/12/purchase/me/item', methods=['POST'])
def item():
return jsonify({
"success": True
})
@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 购买,自然没有用
def pack():
return jsonify({
"success": True
})
@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买,自然没有用
def single():
return jsonify({
"success": True,
"value": [{
"name": "testsingle",
"items": [{
"id": "testsingle",
"type": "single",
"is_available": False
}],
"price": 100,
"orig_price": 100
}]
})
@app.route('/coffee/12/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图
def world_all():
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id:
return jsonify({
"success": True,
"value": {
"current_map": server.arcworld.get_current_map(user_id),
"user_id": user_id,
"maps": server.arcworld.get_world_all(user_id)
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/world/map/me/', methods=['POST']) # 进入地图
def world_in():
headers = request.headers
token = headers['Authorization']
token = token[7:]
map_id = request.form['map_id']
try:
user_id = server.auth.token_get_id(token)
if user_id:
return jsonify({
"success": True,
"value": server.arcworld.get_user_world(user_id, map_id)
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/12/world/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息
def world_one(map_id):
headers = request.headers
token = headers['Authorization']
token = token[7:]
try:
user_id = server.auth.token_get_id(token)
if user_id:
server.arcworld.change_user_current_map(user_id, map_id)
return jsonify({
"success": True,
"value": {
"user_id": user_id,
"current_map": map_id,
"maps": [server.arcworld.get_user_world_info(user_id, map_id)]
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/coffee/<path:path>', methods=['POST']) # 三个设置,写在最后降低优先级
def sys_set(path):
set_arg = path[10:]
headers = request.headers
token = headers['Authorization']
token = token[7:]
value = request.form['value']
try:
user_id = server.auth.token_get_id(token)
if user_id is not None:
server.setme.arc_sys_set(user_id, value, set_arg)
r = server.info.arc_aggregate_small(user_id)
r['value'] = r['value'][0]['value']
return jsonify(r)
else:
return error_return(108)
except:
return error_return(108)
def main():
config = configparser.ConfigParser()
path = r'setting.ini'
config.read(path, encoding="utf-8")
HOST = config.get('CONFIG', 'HOST')
PORT = config.get('CONFIG', 'PORT')
app.config.from_mapping(SECRET_KEY='1145141919810')
app.register_blueprint(web.login.bp)
app.register_blueprint(web.index.bp)
app.run(HOST, PORT)
if __name__ == '__main__':
main()
# Made By Lost 2020.9.11

1
v1.3/run.bat Normal file
View File

@@ -0,0 +1 @@
python main.py

1372
v1.3/server/arcscore.py Normal file

File diff suppressed because it is too large Load Diff

259
v1.3/server/arcworld.py Normal file
View File

@@ -0,0 +1,259 @@
import json
import sqlite3
import os
def int2b(x):
# int与布尔值转换
if x is None or x == 0:
return False
else:
return True
def get_world_name(file_dir='./database/map'):
# 获取所有地图名称,返回列表
L = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.json':
L.append(os.path.splitext(file)[0])
return L
def get_world_info(map_id):
# 读取json文件内容返回字典
f = open('./database/map/'+map_id+'.json', 'r')
world_info = json.load(f)
f.close()
return world_info
def get_user_world_info(user_id, map_id):
# 读取json文件内容加上用户信息返回字典
info = get_world_info(map_id)
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id})
x = c.fetchone()
if x:
info['curr_position'] = x[2]
info['curr_capture'] = x[3]
info['is_locked'] = int2b(x[4])
else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id})
conn.commit()
conn.close()
return info
def get_current_map(user_id):
# 得到user的当前图返回字符串
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select current_map from user where user_id = :a''',
{'a': user_id})
x = c.fetchone()
re = ''
if x:
re = x[0]
conn.commit()
conn.close()
return re
def get_world_all(user_id):
# 读取所有地图信息并处理,返回字典列表
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
worlds = get_world_name()
re = []
for map_id in worlds:
info = get_world_info(map_id)
steps = info['steps']
del info['steps']
rewards = []
for step in steps:
if 'items' in step:
rewards.append(
{'items': step['items'], 'position': step['position']})
info['rewards'] = rewards
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id})
x = c.fetchone()
if x:
info['curr_position'] = x[2]
info['curr_capture'] = x[3]
info['is_locked'] = int2b(x[4])
else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id})
re.append(info)
conn.commit()
conn.close()
return re
def get_user_world(user_id, map_id):
# 获取用户图信息,返回字典
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id})
x = c.fetchone()
re = {
"user_id": user_id,
"curr_position": 0,
"curr_capture": 0,
"is_locked": False,
"map_id": map_id
}
if x:
re['curr_position'] = x[2]
re['curr_capture'] = x[3]
re['is_locked'] = int2b(x[4])
else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id})
conn.commit()
conn.close()
return re
def change_user_current_map(user_id, map_id):
# 改变用户当前图
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''update user set current_map = :a where user_id=:b''', {
'a': map_id, 'b': user_id})
conn.commit()
conn.close()
return None
def play_world_song(user_id, args):
# 声明是世界模式的打歌,并且记录加成信息
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
stamina_multiply = 1
fragment_multiply = 100
prog_boost_multiply = 0
if 'stamina_multiply' in args:
stamina_multiply = int(args['stamina_multiply'])
if 'fragment_multiply' in args:
fragment_multiply = int(args['fragment_multiply'])
if 'prog_boost_multiply' in args:
prog_boost_multiply = int(args['prog_boost_multiply'])
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
'a': user_id, 'b': args['song_id'], 'c': args['difficulty']})
c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', {
'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply})
conn.commit()
conn.close()
return None
def climb_step(user_id, map_id, step, prev_capture, prev_position):
# 爬梯子,返回奖励列表,台阶列表,当前的位置和坐标,图信息
info = get_world_info(map_id)
step_count = int(info['step_count'])
restrict_ids = [[]] * step_count
capture = [0] * step_count
reward_bundle = [""] * step_count # 暂且不用
restrict_id = [""] * step_count
restrict_type = [""] * step_count
items = [[]] * step_count
step_type = [[]] * step_count
speed_limit_value = [0] * step_count
plus_stamina_value = [0] * step_count
for i in info['steps']:
capture[i['position']] = i['capture']
if 'items' in i:
items[i['position']] = i['items']
if 'restrict_id' in i:
restrict_id[i['position']] = i['restrict_id']
if 'restrict_ids' in i:
restrict_ids[i['position']] = i['restrict_ids']
if 'restrict_type' in i:
restrict_type[i['position']] = i['restrict_type']
if 'step_type' in i:
step_type[i['position']] = i['step_type']
if "speedlimit" in i['step_type']:
speed_limit_value[i['position']] = i['speed_limit_value']
if "plusstamina" in i['step_type']:
plus_stamina_value[i['position']] = i['plus_stamina_value']
if info['is_beyond']: # beyond判断
dt = info['beyond_health'] - prev_capture
if dt >= step:
curr_capture = prev_capture + step
else:
curr_capture = info['beyond_health']
i = 0
t = prev_capture + step
while i < step_count and t > 0:
dt = capture[i]
if dt > t:
t = 0
else:
t -= dt
i += 1
if i >= step_count:
curr_position = step_count - 1
else:
curr_position = i
else:
i = prev_position
j = prev_capture
t = step
while t > 0 and i < step_count:
dt = capture[i] - j
if dt > t:
j += t
t = 0
else:
t -= dt
j = 0
i += 1
if i >= step_count:
curr_position = step_count - 1
curr_capture = 0
else:
curr_position = i
curr_capture = j
rewards = []
steps = []
for i in range(prev_position, curr_position+1):
if items[i]:
rewards.append({'position': i, 'items': items[i]})
x = {
"map_id": map_id,
"position": i,
"restrict_ids": restrict_ids[i],
"capture": capture[i],
"reward_bundle": reward_bundle[i],
"restrict_id": restrict_id[i],
"restrict_type": restrict_type[i]
}
if step_type[i]:
x['step_type'] = step_type[i]
if speed_limit_value[i]:
x['speed_limit_value'] = speed_limit_value[i]
if plus_stamina_value[i]:
x['plus_stamina_value'] = plus_stamina_value[i]
steps.append(x)
return rewards, steps, curr_position, curr_capture, info

150
v1.3/server/auth.py Normal file
View File

@@ -0,0 +1,150 @@
import sqlite3
import hashlib
import time
import server.arcworld
def arc_login(name: str, password: str) -> str: # 登录判断
# 查询数据库中的user表验证账号密码返回并记录token
# token采用user_id和时间戳连接后hash生成真的是瞎想的没用bear
# 密码和token的加密方式为 SHA-256
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
c.execute('''select user_id from user where name = :name and password = :password''', {
'name': name, 'password': hash_pwd})
x = c.fetchone()
if x is not None:
user_id = str(x[0])
now = int(time.time() * 1000)
token = hashlib.sha256((user_id + str(now)).encode("utf8")).hexdigest()
c.execute(
'''select exists(select * from login where user_id = :user_id)''', {"user_id": user_id})
if c.fetchone() == (1,): # 删掉多余token
c.execute('''delete from login where user_id = :user_id''',
{'user_id': user_id})
c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', {
'user_id': user_id, 'access_token': token})
conn.commit()
conn.close()
return token
conn.commit()
conn.close()
return None
def arc_register(name: str, password: str): # 注册
# 账号注册只记录hash密码和用户名生成user_id和user_code自动登录返回token
# token和密码的处理同登录部分
def build_user_code(c):
# 生成9位的user_code用的自然是随机
import random
flag = True
while flag:
user_code = ''.join([str(random.randint(0, 9)) for i in range(9)])
c.execute('''select exists(select * from user where user_code = :user_code)''',
{'user_code': user_code})
if c.fetchone() == (0,):
flag = False
return user_code
def build_user_id(c):
# 生成user_id往后加1
c.execute('''select max(user_id) from user''')
x = c.fetchone()
if x[0] is not None:
return x[0] + 1
else:
return 2000001
# def insert_user_char(c, user_id):
# # 为用户添加所有可用角色
# for i in range(0, 38):
# if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
# sql = 'insert into user_char values('+str(user_id)+','+str(
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
# c.execute(sql)
# else:
# if i != 5:
# sql = 'insert into user_char values('+str(user_id)+','+str(
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
# c.execute(sql)
def insert_user_char(c, user_id):
# 为用户添加所有可用角色
c.execute('''select * from character''')
x = c.fetchall()
if x != []:
for i in x:
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
c.execute(
'''select exists(select * from user where name = :name)''', {'name': name})
if c.fetchone() == (0,):
user_code = build_user_code(c)
user_id = build_user_id(c)
now = int(time.time() * 1000)
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map)
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '')
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd})
c.execute('''insert into recent30(user_id) values(:user_id)''', {
'user_id': user_id})
token = hashlib.sha256(
(str(user_id) + str(now)).encode("utf8")).hexdigest()
c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', {
'user_id': user_id, 'access_token': token})
insert_user_char(c, user_id)
conn.commit()
conn.close()
return user_id, token, 0
else:
conn.commit()
conn.close()
return None, None, 101
def token_get_id(token: str):
# 用token获取id没有考虑不同用户token相同情况说不定会有bug
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select user_id from login where access_token = :token''', {
'token': token})
x = c.fetchone()
if x is not None:
conn.commit()
conn.close()
return x[0]
else:
conn.commit()
conn.close()
return None
def code_get_id(user_code):
# 用user_code获取id
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select user_id from user where user_code = :a''',
{'a': user_code})
x = c.fetchone()
if x is not None:
conn.commit()
conn.close()
return x[0]
else:
conn.commit()
conn.close()
return None

491
v1.3/server/info.py Normal file
View File

@@ -0,0 +1,491 @@
import sqlite3
import server.arcworld
def int2b(x):
# int与布尔值转换
if x is None or x == 0:
return False
else:
return True
def get_recent_score(c, user_id):
# 得到用户最近一次的成绩,返回列表
c.execute('''select * from user where user_id = :x''', {'x': user_id})
x = c.fetchone()
if x is not None:
if x[11] is not None:
c.execute('''select best_clear_type from best_score where user_id=:u and song_id=:s and difficulty=:d''', {
'u': user_id, 's': x[11], 'd': x[12]})
y = c.fetchone()
if y is not None:
best_clear_type = y[0]
else:
best_clear_type = x[21]
return [{
"rating": x[22],
"modifier": x[19],
"time_played": x[20],
"health": x[18],
"best_clear_type": best_clear_type,
"clear_type": x[21],
"miss_count": x[17],
"near_count": x[16],
"perfect_count": x[15],
"shiny_perfect_count": x[14],
"score": x[13],
"difficulty": x[12],
"song_id": x[11]
}]
return []
def get_user_character(c, user_id):
# 得到用户拥有的角色列表,返回列表
c.execute('''select * from user_char where user_id = :user_id''',
{'user_id': user_id})
x = c.fetchall()
if x != []:
s = []
for i in x:
char_name = ''
c.execute(
'''select name from character where character_id = :x''', {'x': i[1]})
y = c.fetchone()
if y is not None:
char_name = y[0]
s.append({
"is_uncapped_override": int2b(i[14]),
"is_uncapped": int2b(i[13]),
"uncap_cores": [],
"char_type": i[12],
"skill_id_uncap": i[11],
"skill_requires_uncap": int2b(i[10]),
"skill_unlock_level": i[9],
"skill_id": i[8],
"overdrive": i[7],
"prog": i[6],
"frag": i[5],
"level_exp": i[4],
"exp": i[3],
"level": i[2],
"name": char_name,
"character_id": i[1]
})
return s
else:
return []
def get_user_friend(c, user_id):
# 得到用户的朋友列表,返回列表
c.execute('''select user_id_other from friend where user_id_me = :user_id''', {
'user_id': user_id})
x = c.fetchall()
s = []
if x != [] and x[0][0] is not None:
for i in x:
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': i[0], 'y': user_id})
if c.fetchone() == (1,):
is_mutual = True
else:
is_mutual = False
c.execute('''select * from user where user_id = :x''', {'x': i[0]})
y = c.fetchone()
if y is not None:
s.append({
"is_mutual": is_mutual,
"is_char_uncapped_override": int2b(y[9]),
"is_char_uncapped": int2b(y[8]),
"is_skill_sealed": int2b(y[7]),
"rating": y[5],
"join_date": int(y[3]),
"character": y[6],
"recent_score": get_recent_score(c, i[0]),
"name": y[1],
"user_id": i[0]
})
return s
def get_value_0(c, user_id):
# 构造value id=0的数据返回字典
c.execute('''select * from user where user_id = :x''', {'x': user_id})
x = c.fetchone()
r = {}
if x is not None:
user_character = get_user_character(c, user_id)
characters = []
for i in user_character:
characters.append(i['character_id'])
r = {"is_aprilfools": False,
"curr_available_maps": [],
"character_stats": user_character,
"friends": get_user_friend(c, user_id),
"settings": {
"favorite_character": x[23],
"is_hide_rating": int2b(x[10]),
"max_stamina_notification_enabled": int2b(x[24])
},
"user_id": user_id,
"name": x[1],
"user_code": x[4],
"display_name": x[1],
"ticket": 114514,
"character": x[6],
"is_locked_name_duplicate": False,
"is_skill_sealed": int2b(x[7]),
"current_map": x[25],
"prog_boost": 0,
"next_fragstam_ts": -1,
"max_stamina_ts": 1586274871917,
"stamina": 12,
"world_unlocks": [],
"world_songs": ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster", "cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight"],
"singles": ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "buchigireberserker2"],
"packs": ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"],
"characters": characters,
"cores": [],
"recent_score": get_recent_score(c, user_id),
"max_friend": 50,
"rating": x[5],
"join_date": int(x[3])
}
return r
def arc_aggregate_small(user_id):
# 返回用户数据
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
r = {"success": True,
"value": [{
"id": 0,
"value": get_value_0(c, user_id)
}]}
conn.commit()
conn.close()
return r
def arc_aggregate_big(user_id):
# 返回用户数据和地图歌曲信息
# 因为没有整理地图和曲包数据(不需要世界模式),所以直接复制了
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
r = {"success": True,
"value": [{
"id": 0,
"value": get_value_0(c, user_id)
}, {
"id": 1,
"value": [{
"name": "core",
"items": [{
"id": "core",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "shiawase",
"items": [{
"id": "shiawase",
"type": "pack",
"is_available": True
}, {
"id": "kou",
"type": "character",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1552089600000,
"discount_to": 1552694399000
}, {
"name": "dynamix",
"items": [{
"id": "dynamix",
"type": "pack",
"is_available": True
}, {
"id": "sapphire",
"type": "character",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "mirai",
"items": [{
"id": "mirai",
"type": "pack",
"is_available": True
}, {
"id": "lethe",
"type": "character",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1552089600000,
"discount_to": 1552694399000
}, {
"name": "yugamu",
"items": [{
"id": "yugamu",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "lanota",
"items": [{
"id": "lanota",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "nijuusei",
"items": [{
"id": "nijuusei",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "rei",
"items": [{
"id": "rei",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "tonesphere",
"items": [{
"id": "tonesphere",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "groovecoaster",
"items": [{
"id": "groovecoaster",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "zettai",
"items": [{
"id": "zettai",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500,
"discount_from": 1583712000000,
"discount_to": 1584316799000
}, {
"name": "chunithm",
"items": [{
"id": "chunithm",
"type": "pack",
"is_available": True
}],
"price": 300,
"orig_price": 300
}, {
"name": "prelude",
"items": [{
"id": "prelude",
"type": "pack",
"is_available": True
}],
"price": 400,
"orig_price": 400
}, {
"name": "omatsuri",
"items": [{
"id": "omatsuri",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500
}, {
"name": "vs",
"items": [{
"id": "vs",
"type": "pack",
"is_available": True
}],
"price": 500,
"orig_price": 500
}, {
"name": "extend",
"items": [{
"id": "extend",
"type": "pack",
"is_available": True
}],
"price": 700,
"orig_price": 700
}]
}, {
"id": 2,
"value": {}
}, {
"id": 3,
"value": {
"max_stamina": 12,
"stamina_recover_tick": 1800000,
"core_exp": 250,
"curr_ts": 1599547606825,
"level_steps": [{
"level": 1,
"level_exp": 0
}, {
"level": 2,
"level_exp": 50
}, {
"level": 3,
"level_exp": 100
}, {
"level": 4,
"level_exp": 150
}, {
"level": 5,
"level_exp": 200
}, {
"level": 6,
"level_exp": 300
}, {
"level": 7,
"level_exp": 450
}, {
"level": 8,
"level_exp": 650
}, {
"level": 9,
"level_exp": 900
}, {
"level": 10,
"level_exp": 1200
}, {
"level": 11,
"level_exp": 1600
}, {
"level": 12,
"level_exp": 2100
}, {
"level": 13,
"level_exp": 2700
}, {
"level": 14,
"level_exp": 3400
}, {
"level": 15,
"level_exp": 4200
}, {
"level": 16,
"level_exp": 5100
}, {
"level": 17,
"level_exp": 6100
}, {
"level": 18,
"level_exp": 7200
}, {
"level": 19,
"level_exp": 8500
}, {
"level": 20,
"level_exp": 10000
}, {
"level": 21,
"level_exp": 11500
}, {
"level": 22,
"level_exp": 13000
}, {
"level": 23,
"level_exp": 14500
}, {
"level": 24,
"level_exp": 16000
}, {
"level": 25,
"level_exp": 17500
}, {
"level": 26,
"level_exp": 19000
}, {
"level": 27,
"level_exp": 20500
}, {
"level": 28,
"level_exp": 22000
}, {
"level": 29,
"level_exp": 23500
}, {
"level": 30,
"level_exp": 25000
}],
"world_ranking_enabled": False,
"is_byd_chapter_unlocked": True
}
}, {
"id": 4,
"value": []
}, {
"id": 5,
"value": {
"current_map": server.arcworld.get_current_map(user_id),
"user_id": user_id,
"maps": server.arcworld.get_world_all(user_id)
}
}
]}
conn.commit()
conn.close()
return r

155
v1.3/server/setme.py Normal file
View File

@@ -0,0 +1,155 @@
import sqlite3
import server.info
def b2int(x):
# int与布尔值转换
if x:
return 1
else:
return 0
def int2b(x):
# int与布尔值转换
if x is None or x == 0:
return False
else:
return True
def change_char(user_id, character_id, skill_sealed):
# 角色改变,包括技能封印的改变,返回成功与否的布尔值
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id})
x = c.fetchone()
if x is not None:
if skill_sealed == 'false':
skill_sealed = False
else:
skill_sealed = True
c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id})
conn.commit()
conn.close()
return True
conn.commit()
conn.close()
return False
def change_char_uncap(user_id, character_id):
# 角色觉醒改变,返回字典
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id})
x = c.fetchone()
r = None
if x is not None and x[0] == 1:
c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', {
'a': b2int(x[1] == 0), 'b': user_id})
c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
c.execute('''select * from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id})
y = c.fetchone()
c.execute(
'''select name from character where character_id = :x''', {'x': y[1]})
z = c.fetchone()
if z is not None:
char_name = z[0]
if y is not None:
r = {
"is_uncapped_override": int2b(y[14]),
"is_uncapped": int2b(y[13]),
"uncap_cores": [],
"char_type": y[12],
"skill_id_uncap": y[11],
"skill_requires_uncap": int2b(y[10]),
"skill_unlock_level": y[9],
"skill_id": y[8],
"overdrive": y[7],
"prog": y[6],
"frag": y[5],
"level_exp": y[4],
"exp": y[3],
"level": y[2],
"name": char_name,
"character_id": y[1]
}
conn.commit()
conn.close()
return r
def arc_sys_set(user_id, value, set_arg):
# 三个设置PTT隐藏、体力满通知、最爱角色无返回
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
if 'favorite_character' in set_arg:
value = int(value)
c.execute('''update user set favorite_character = :a where user_id = :b''', {
'a': value, 'b': user_id})
else:
if value == 'false':
value = False
else:
value = True
if 'is_hide_rating' in set_arg:
c.execute('''update user set is_hide_rating = :a where user_id = :b''', {
'a': b2int(value), 'b': user_id})
if 'max_stamina_notification_enabled' in set_arg:
c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', {
'a': b2int(value), 'b': user_id})
conn.commit()
conn.close()
return None
def arc_add_friend(user_id, friend_id):
# 加好友返回好友列表或者是错误码602、604
if user_id == friend_id:
return 604
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': user_id, 'y': friend_id})
r = None
if c.fetchone() == (0,):
c.execute('''insert into friend values(:a, :b)''',
{'a': user_id, 'b': friend_id})
r = server.info.get_user_friend(c, user_id)
else:
return 602
conn.commit()
conn.close()
return r
def arc_delete_friend(user_id, friend_id):
# 删好友,返回好友列表
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': user_id, 'y': friend_id})
r = None
if c.fetchone() == (1,):
c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
{'x': user_id, 'y': friend_id})
r = server.info.get_user_friend(c, user_id)
conn.commit()
conn.close()
return r

3
v1.3/setting.ini Normal file
View File

@@ -0,0 +1,3 @@
[CONFIG]
HOST = 192.168.1.113
PORT = 80

217
v1.3/static/style.css Normal file
View File

@@ -0,0 +1,217 @@
html {
font-family: sans-serif;
background: #eee;
padding: 1rem;
}
body {
max-width: 960px;
margin: 0 auto;
background: white;
}
h1 {
font-family: serif;
color: #377ba8;
margin: 1rem 0;
}
a {
text-decoration: none;
color: #377ba8;
}
hr {
border: none;
border-top: 1px solid lightgray;
}
nav {
background: lightgray;
display: flex;
align-items: center;
padding: 0 0.5rem;
}
nav h1 {
flex: auto;
margin: 0;
}
nav h1 a {
text-decoration: none;
padding: 0.25rem 0.5rem;
}
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
nav ul li a,
nav ul li span,
header .action {
display: block;
padding: 0.5rem;
}
.content {
padding: 0 1rem 1rem;
}
.content>header {
border-bottom: 1px solid lightgray;
display: flex;
align-items: flex-end;
}
.content>header h1 {
flex: auto;
margin: 1rem 0 0.25rem 0;
}
.flash {
margin: 1em 0;
padding: 1em;
background: #cae6f6;
border: 1px solid #377ba8;
}
.post>header {
display: flex;
align-items: flex-end;
font-size: 0.85em;
}
.post>header>div:first-of-type {
flex: auto;
}
.post>header h1 {
font-size: 1.5em;
margin-bottom: 0;
}
.post .about {
color: slategray;
font-style: italic;
}
.post .body {
white-space: pre-line;
}
.content:last-child {
margin-bottom: 0;
}
.content form {
margin: 1em 0;
display: flex;
flex-direction: column;
}
.content label {
font-weight: bold;
margin-bottom: 0.5em;
}
.content input,
.content textarea {
margin-bottom: 1em;
}
.content textarea {
min-height: 12em;
resize: vertical;
}
input.danger {
color: #cc2f2e;
}
input[type=submit] {
align-self: start;
min-width: 10em;
}
.score-item {
margin-bottom: 10px;
clear: both;
}
.song-title {
font-size: 1.3em;
font-weight: bold;
display: inline-block;
}
.difficulty_pst {
font-size: 0.9em;
background-color: rgb(10, 130, 190);
color: white;
}
.difficulty_prs {
font-size: 0.9em;
background-color: rgb(100, 140, 60);
color: white;
}
.difficulty_ftr {
font-size: 0.9em;
background-color: rgb(80, 25, 75);
color: white;
}
.difficulty_byd {
font-size: 0.9em;
background-color: rgb(130, 35, 40);
color: white;
}
.rank {
font-size: 0.8em;
margin-left: 4px;
padding: 0 4px;
}
.rank_big {
font-size: 1.2em;
margin-left: 4px;
padding: 0 4px;
}
.song-detail {
font-size: 0.8em;
float: right;
text-align: right;
}
.song-score {
font-size: 1.375em;
font-family: Arial;
}
.song-clear-type {
font-size: 0.875em;
padding-left: 0.625em;
}
.title {
font-size: 1.375em;
}
.name {
font-size: 1.12em;
font-weight: bold;
}
.footer{
font-size: 0.5em;
color: grey;
text-align: center;
}

23
v1.3/templates/base.html Normal file
View File

@@ -0,0 +1,23 @@
<!doctype html>
<title>{% block title %}{% endblock %} - Arcaea Server</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
<h1>Arcaea Server</h1>
<ul>
{% if g.user %}
<li><span>{{ g.user['username'] }}</span>
<li><a href="{{ url_for('index.index') }}">Home</a>
<li><a href="{{ url_for('login.logout') }}">Log Out</a> {% else %}
<li><a href="{{ url_for('login.login') }}">Log In</a> {% endif %}
</ul>
</nav>
<section class="content">
<header>
{% block header %}{% endblock %}
</header>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %} {% block content %}{% endblock %}
</section>
<footer id="footer" class="footer">Made by Lost@2020</footer>

View File

@@ -0,0 +1,81 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}All players{% endblock %}</h1>
{% endblock %}
{% block content %}
{% if posts %}
{% for user in posts %}
<div id="user-info">
<div class="name">{{user['name']}}
<span class="rank">UID: {{user['user_id']}}</span>
<span class="rank">User code: {{user['user_code']}}</span>
</div>
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
<div class="ptt">PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
<div>
<div>Recent plays: </div>
<div>
<div class="score-item">
<span class="song-title">
{{user['song_id']}}
</span>
{% if user['difficulty'] == 0 %}
<span class="difficulty_pst">PST</span>
{% elif user['difficulty'] == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif user['difficulty'] == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<div class="song-detail">
<br />
<table>
<tbody>
<tr>
<td>PURE: </td>
<td>{{user['perfect_count']}}</td>
<td> {{'(' ~ user['shiny_perfect_count'] ~ ')'}}</td>
</tr>
<tr>
<td>FAR: </td>
<td>{{user['near_count']}}</td>
<td></td>
</tr>
<tr>
<td>LOST: </td>
<td>{{user['miss_count']}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="song-score">{{user['score']}}</div>
<div class="song-clear-type">
{% if user['clear_type'] == 3 %}Pure Memory
{% elif user['clear_type'] == 2 %}Full Recall
{% elif user['clear_type'] == 5 %}Hard Clear
{% elif user['clear_type'] == 1 %}Normal Clear
{% elif user['clear_type'] == 4 %}Easy Clear
{% else%}Track Lost
{% endif %}
</div>
<div class="song-rating">成绩评价 Rating: {{user['rating']}}</div>
<div class="song-clear-date">日期 Date:
{{user['time_played']}}
</div>
</div>
</div>
</div>
</div>
{% if not loop.last %}
<hr />
<br />
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}All songs{% endblock %}</h1>
{% endblock %}
{% block content %}
{% if posts %}<br />
{% for song in posts %}
<div class="score-item">
<span>Sid: </span>
<span class="song-title">{{song['song_id']}}</span>
<br />
<span>Name_en: </span>
<span class="song-title">{{song['name_en']}}</span>
<br />
<div>铺面定数 Chart const: </div>
{% if song['rating_pst'] %}
<span class="difficulty_pst">PST</span>
<span class="song-rating">{{song['rating_pst']}}</span>
{% endif %}
<br />
{% if song['rating_prs'] %}
<span class="difficulty_prs">PRS</span>
<span class="song-rating">{{song['rating_prs']}}</span>
{% endif %}
<br />
{% if song['rating_ftr'] %}
<span class="difficulty_ftr">FTR</span>
<span class="song-rating">{{song['rating_ftr']}}</span>
{% endif %}
<br />
{% if song['rating_byn'] %}
<span class="difficulty_byd">BYD</span>
<span class="song-rating">{{song['rating_byn']}}</span>
{% endif %}
</div>
{% if not loop.last %}
<br />
<hr />
<br />
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,35 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Change the songs{% endblock %}</h1>
{% endblock %}
{% block content %}
<form action="/web/changesong/addsong" method="post">
<div class="title">Add the song</div>
<label for="sid">SID of the song</label>
<input name="sid" id="sid" required>
<label for="name_en">English name of the song(Not important but neccessary)</label>
<input name="name_en" id="name_en" required>
<label for="rating_pst">Past chart const</label>
<input name="rating_pst" id="rating_pst" required>
<label for="rating_prs">Present chart const</label>
<input name="rating_prs" id="rating_prs" required>
<label for="rating_ftr">Future chart const</label>
<input name="rating_ftr" id="rating_ftr" required>
<label for="rating_byd">Beyond chart const</label>
<input name="rating_byd" id="rating_byd" required>
<div class="content">如果没有某个铺面,应该填入-1。</div>
<div class="content">If there is no some chart, fill in -1 please.</div>
<input type="submit" value="Add">
</form>
<br />
<hr />
<form action="/web/changesong/deletesong" method="post">
<div class="title">Delete the song</div>
<label for="sid">SID of the song</label>
<input name="sid" id="sid" required>
<input type="submit" value="Delete">
</form>
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Index{% endblock %}</h1>
{% endblock %}
{% block content %}
<h1>说明 Statement</h1>
<p>这是Arcaea Server的后台管理协助系统可以进行一些简单的操作</br>
This is the background management assistance system of Arcaea Server, which can be used to do some simple
operations.
</p>
<h1>游戏方面 Game</h1>
<a href="{{ url_for('index.single_player_score') }}">单个玩家成绩查询 Single player score</a></br></br>
<a href="{{ url_for('index.single_player_ptt') }}">单个玩家PTT详情查询 Single player ptt</a></br></br>
<a href="{{ url_for('index.all_player') }}">所有玩家信息查询 All players</a></br></br>
<a href="{{ url_for('index.all_song') }}">铺面信息查询 All songs</a></br></br>
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
<hr>
<h1>系统方面 System</h1>
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a>
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Log In{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Log In">
</form>
{% endblock %}

View File

@@ -0,0 +1,108 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Single chart top{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="sid">SID of the song</label>
<span>模糊查询,只返回第一个</span>
<span>Fuzzy query,and only return the first one.</span>
<input name="sid" id="sid">
<label for="difficulty">Difficulty</label>
<select name='difficulty' id='difficulty'>
<option value="0" selected>Past</option>
<option value="1">Present</option>
<option value="2">Future</option>
<option value="3">Beyond</option>
</select>
<br />
<input type="submit" value="Find">
</br>
</br>
</br>
{% if song_id %}
<div>
<span class="song-title">
{{song_id}}
</span>
{% if difficulty == 0 %}
<span class="difficulty_pst">PST</span>
{% elif difficulty == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif difficulty == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<br />
<div class="song-title">
{{song_name_en}}
</div>
</div>
{% endif %}
<br />
<hr />
{% for post in posts %}
<div class="score-item">
<div>
<span class='rank_big'>{{'#' ~ post['rank']}}</span>
<span class="name">
{{post['name']}}
</span>
<span class="rank">UID: {{post['user_id']}}</span>
</div>
<div class="song-detail">
<table>
<tbody>
<tr>
<td>PURE: </td>
<td>{{post['perfect_count']}}</td>
<td> {{'(' ~ post['shiny_perfect_count'] ~ ')'}}</td>
</tr>
<tr>
<td>FAR: </td>
<td>{{post['near_count']}}</td>
<td></td>
</tr>
<tr>
<td>LOST: </td>
<td>{{post['miss_count']}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="song-score">{{post['score']}}</div>
<div class="song-clear-type">
{% if post['clear_type'] == 3 %}Pure Memory
{% elif post['clear_type'] == 2 %}Full Recall
{% elif post['clear_type'] == 5 %}Hard Clear
{% elif post['clear_type'] == 1 %}Normal Clear
{% elif post['clear_type'] == 4 %}Easy Clear
{% else%}Track Lost
{% endif %}
<span class="song-clear-type" style="margin-left: 1.875em;">
{% if post['best_clear_type'] == 3 %}(Pure Memory)
{% elif post['best_clear_type'] == 2 %}(Full Recall)
{% elif post['best_clear_type'] == 5 %}(Hard Clear)
{% elif post['best_clear_type'] == 1 %}(Normal Clear)
{% elif post['best_clear_type'] == 4 %}(Easy Clear)
{% else%}(Track Lost)
{% endif %}
</span>
</div>
<div class="song-clear-date">日期 Date:
{{post['time_played']}}
</div>
</div>
{% if not loop.last %}
</br>
{% endif %}
{% endfor %}
</form>
{% endblock %}

View File

@@ -0,0 +1,85 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Single player score{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="name">Arcaea Username</label>
<input name="name" id="name">
or<br />
<label for="user_code">Arcaea User Code</label>
<input name="user_code" id="user_code">
<input type="submit" value="Find">
</br>
</br>
</br>
{% for post in posts %}
<div class="score-item">
<span class="song-title">
{{post['song_id']}}
</span>
{% if post['difficulty'] == 0 %}
<span class="difficulty_pst">PST</span>
{% elif post['difficulty'] == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif post['difficulty'] == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<span class='rank'>{{'#' ~ post['rank']}}</span>
<div class="song-detail">
</br>
<table>
<tbody>
<tr>
<td>PURE: </td>
<td>{{post['perfect_count']}}</td>
<td> {{'(' ~ post['shiny_perfect_count'] ~ ')'}}</td>
</tr>
<tr>
<td>FAR: </td>
<td>{{post['near_count']}}</td>
<td></td>
</tr>
<tr>
<td>LOST: </td>
<td>{{post['miss_count']}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="song-score">{{post['score']}}</div>
<div class="song-clear-type">
{% if post['clear_type'] == 3 %}Pure Memory
{% elif post['clear_type'] == 2 %}Full Recall
{% elif post['clear_type'] == 5 %}Hard Clear
{% elif post['clear_type'] == 1 %}Normal Clear
{% elif post['clear_type'] == 4 %}Easy Clear
{% else%}Track Lost
{% endif %}
<span class="song-clear-type" style="margin-left: 1.875em;">
{% if post['best_clear_type'] == 3 %}(Pure Memory)
{% elif post['best_clear_type'] == 2 %}(Full Recall)
{% elif post['best_clear_type'] == 5 %}(Hard Clear)
{% elif post['best_clear_type'] == 1 %}(Normal Clear)
{% elif post['best_clear_type'] == 4 %}(Easy Clear)
{% else%}(Track Lost)
{% endif %}
</span>
</div>
<div class="song-rating">成绩评价 Rating: {{post['rating']}}</div>
<div class="song-clear-date">日期 Date:
{{post['time_played']}}
</div>
</div>
{% if not loop.last %}
</br>
{% endif %}
{% endfor %}
</form>
{% endblock %}

View File

@@ -0,0 +1,191 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Single player ptt{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="name">Arcaea Username</label>
<input name="name" id="name">
or<br />
<label for="user_code">Arcaea User Code</label>
<input name="user_code" id="user_code">
<input type="submit" value="Find">
<br />
<br />
<br />
{% if user %}
<hr />
<div id="user-info">
<div class="title">玩家信息 Player information</div>
<div class="name">{{user['name']}}
<span class="rank">UID: {{user['user_id']}}</span>
<span class="rank">User code: {{user['user_code']}}</span>
</div>
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
<div class="ptt">PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
<div class="ptt">Best 30 PTT: {{bestptt}}</div>
<div class="ptt">Recent 10 PTT: {{recentptt}}</div>
<div>
<div>Recent plays: </div>
<div>
<div class="score-item">
<span class="song-title">
{{user['song_id']}}
</span>
{% if user['difficulty'] == 0 %}
<span class="difficulty_pst">PST</span>
{% elif user['difficulty'] == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif user['difficulty'] == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<div class="song-detail">
<br />
<table>
<tbody>
<tr>
<td>PURE: </td>
<td>{{user['perfect_count']}}</td>
<td> {{'(' ~ user['shiny_perfect_count'] ~ ')'}}</td>
</tr>
<tr>
<td>FAR: </td>
<td>{{user['near_count']}}</td>
<td></td>
</tr>
<tr>
<td>LOST: </td>
<td>{{user['miss_count']}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="song-score">{{user['score']}}</div>
<div class="song-clear-type">
{% if user['clear_type'] == 3 %}Pure Memory
{% elif user['clear_type'] == 2 %}Full Recall
{% elif user['clear_type'] == 5 %}Hard Clear
{% elif user['clear_type'] == 1 %}Normal Clear
{% elif user['clear_type'] == 4 %}Easy Clear
{% else%}Track Lost
{% endif %}
</div>
<div class="song-rating">成绩评价 Rating: {{user['rating']}}</div>
<div class="song-clear-date">日期 Date:
{{user['time_played']}}
</div>
</div>
</div>
</div>
</div>
<hr />
{% if posts %}
<div class="title">Best 30</div>
{% endif %}
{% for post in posts %}
<div class="score-item">
<span class="song-title">
{{post['song_id']}}
</span>
{% if post['difficulty'] == 0 %}
<span class="difficulty_pst">PST</span>
{% elif post['difficulty'] == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif post['difficulty'] == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<span class='rank'>{{'#' ~ post['rank']}}</span>
<div class="song-detail">
<br />
<table>
<tbody>
<tr>
<td>PURE: </td>
<td>{{post['perfect_count']}}</td>
<td> {{'(' ~ post['shiny_perfect_count'] ~ ')'}}</td>
</tr>
<tr>
<td>FAR: </td>
<td>{{post['near_count']}}</td>
<td></td>
</tr>
<tr>
<td>LOST: </td>
<td>{{post['miss_count']}}</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="song-score">{{post['score']}}</div>
<div class="song-clear-type">
{% if post['clear_type'] == 3 %}Pure Memory
{% elif post['clear_type'] == 2 %}Full Recall
{% elif post['clear_type'] == 5 %}Hard Clear
{% elif post['clear_type'] == 1 %}Normal Clear
{% elif post['clear_type'] == 4 %}Easy Clear
{% else%}Track Lost
{% endif %}
<span class="song-clear-type" style="margin-left: 1.875em;">
{% if post['best_clear_type'] == 3 %}(Pure Memory)
{% elif post['best_clear_type'] == 2 %}(Full Recall)
{% elif post['best_clear_type'] == 5 %}(Hard Clear)
{% elif post['best_clear_type'] == 1 %}(Normal Clear)
{% elif post['best_clear_type'] == 4 %}(Easy Clear)
{% else%}(Track Lost)
{% endif %}
</span>
</div>
<div class="song-rating">成绩评价 Rating: {{post['rating']}}</div>
<div class="song-clear-date">日期 Date:
{{post['time_played']}}
</div>
</div>
{% if not loop.last %}
<br />
{% endif %}
{% endfor %}
<hr />
{% if recent %}
<div class="title">Recent 30</div>
{% for i in recent %}
{% if i %}
<div class="score-item">
<span class="song-title">
{{i['song_id']}}
</span>
{% if i['difficulty'] == 0 %}
<span class="difficulty_pst">PST</span>
{% elif i['difficulty'] == 1 %}
<span class="difficulty_prs">PRS</span>
{% elif i['difficulty'] == 2 %}
<span class="difficulty_ftr">FTR</span>
{% else %}
<span class="difficulty_byd">BYD</span>
{% endif %}
<span class='rank'>{{loop.index}}</span>
<div class="song-rating">成绩评价 Rating: {{i['rating']}}</div>
</div>
{% if not loop.last %}
<br />
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
</form>
{% endblock %}

View File

@@ -0,0 +1,21 @@
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Update databases{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
<label for="name">Old database</label>
<input type="file" name="file">
<input type="submit" value="Submit">
</form>
<div class="content">
这里可以将旧版本的数据库同步到新版本的数据库,并刷新用户拥有的角色列表。<br />
可上传文件: arcaea_database.db和arcsong.db<br />
新数据库不存在的数据会被添加,存在的数据将不会被改变。<br /><br />
Here you can synchronize the old version of the database to the new version of the database and refresh the list of
characters owned by players.<br />
Uploadable files: arcaea_database.db & arcsong.db<br />
Data that does not exist in the new database will be added and the existing data will not be changed.
</div>
{% endblock %}

360
v1.3/web/index.py Normal file
View File

@@ -0,0 +1,360 @@
from flask import (
Blueprint, flash, g, redirect, render_template, request, url_for
)
from web.login import login_required
from werkzeug.utils import secure_filename
import sqlite3
import web.webscore
import web.system
import time
import server.arcscore
import os
UPLOAD_FOLDER = 'database'
ALLOWED_EXTENSIONS = {'db'}
bp = Blueprint('index', __name__, url_prefix='/web')
def is_number(s):
try: # 判断字符串s是浮点数
float(s)
return True
except ValueError:
pass
return False
@bp.route('/index')
@bp.route('/')
@login_required
def index():
# 主页
return render_template('web/index.html')
@bp.route('/singleplayer', methods=['POST', 'GET'])
@login_required
def single_player_score():
# 单个玩家分数查询
if request.method == 'POST':
name = request.form['name']
user_code = request.form['user_code']
error = None
if name or user_code:
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
if user_code:
c.execute('''select user_id from user where user_code=:a''', {
'a': user_code})
else:
c.execute(
'''select user_id from user where name=:a''', {'a': name})
user_id = c.fetchone()
posts = []
if user_id:
user_id = user_id[0]
posts = web.webscore.get_user_score(c, user_id)
if not posts:
error = '无成绩 No score.'
else:
error = '玩家不存在 The player does not exist.'
conn.commit()
conn.close()
else:
error = '输入为空 Null Input.'
if error:
flash(error)
else:
return render_template('web/singleplayer.html', posts=posts)
return render_template('web/singleplayer.html')
@bp.route('/singleplayerptt', methods=['POST', 'GET'])
@login_required
def single_player_ptt():
# 单个玩家PTT详情查询
if request.method == 'POST':
name = request.form['name']
user_code = request.form['user_code']
error = None
if name or user_code:
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
if user_code:
c.execute('''select user_id from user where user_code=:a''', {
'a': user_code})
else:
c.execute(
'''select user_id from user where name=:a''', {'a': name})
user_id = c.fetchone()
posts = []
if user_id:
user_id = user_id[0]
user = web.webscore.get_user(c, user_id)
posts = web.webscore.get_user_score(c, user_id, 30)
recent, recentptt = web.webscore.get_user_recent30(c, user_id)
if not posts:
error = '无成绩 No score.'
else:
bestptt = 0
for i in posts:
if i['rating']:
bestptt += i['rating']
bestptt = bestptt / 30
else:
error = '玩家不存在 The player does not exist.'
conn.commit()
conn.close()
else:
error = '输入为空 Null Input.'
if error:
flash(error)
else:
return render_template('web/singleplayerptt.html', posts=posts, user=user, recent=recent, recentptt=recentptt, bestptt=bestptt)
return render_template('web/singleplayerptt.html')
@bp.route('/allplayer', methods=['GET'])
@login_required
def all_player():
# 所有玩家数据按照ptt排序
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select * from user order by rating_ptt DESC''')
x = c.fetchall()
error = None
if x:
posts = []
for i in x:
join_data = None
time_played = None
if i[3]:
join_date = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(int(i[3])//1000))
if i[20]:
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(int(i[20])//1000))
posts.append({'name': i[1],
'user_id': i[0],
'join_date': join_date,
'user_code': i[4],
'rating_ptt': i[5],
'song_id': i[11],
'difficulty': i[12],
'score': i[13],
'shiny_perfect_count': i[14],
'perfect_count': i[15],
'near_count': i[16],
'miss_count': i[17],
'time_played': time_played,
'clear_type': i[21],
'rating': i[22]
})
else:
error = '没有玩家数据 No player data.'
conn.commit()
conn.close()
if error:
flash(error)
return render_template('web/allplayer.html')
else:
return render_template('web/allplayer.html', posts=posts)
@bp.route('/allsong', methods=['GET'])
@login_required
def all_song():
# 所有歌曲数据
def defnum(x):
# 定数转换
if x >= 0:
return x / 10
else:
return None
conn = sqlite3.connect('./database/arcsong.db')
c = conn.cursor()
c.execute('''select * from songs''')
x = c.fetchall()
error = None
if x:
posts = []
for i in x:
posts.append({'song_id': i[0],
'name_en': i[1],
'rating_pst': defnum(i[12]),
'rating_prs': defnum(i[13]),
'rating_ftr': defnum(i[14]),
'rating_byn': defnum(i[15])
})
else:
error = '没有铺面数据 No song data.'
conn.commit()
conn.close()
if error:
flash(error)
return render_template('web/allsong.html')
else:
return render_template('web/allsong.html', posts=posts)
@bp.route('/singlecharttop', methods=['GET', 'POST'])
@login_required
def single_chart_top():
# 歌曲排行榜
if request.method == 'POST':
song_name = request.form['sid']
difficulty = request.form['difficulty']
if difficulty.isdigit():
difficulty = int(difficulty)
error = None
conn = sqlite3.connect('./database/arcsong.db')
c = conn.cursor()
song_name = '%'+song_name+'%'
c.execute('''select sid, name_en from songs where sid like :a limit 1''',
{'a': song_name})
x = c.fetchone()
conn.commit()
conn.close()
print(x)
if x:
song_id = x[0]
posts = server.arcscore.arc_score_top(song_id, difficulty, -1)
for i in posts:
i['time_played'] = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(i['time_played']))
else:
error = '查询为空 No song.'
if not error:
return render_template('web/singlecharttop.html', posts=posts, song_name_en=x[1], song_id=song_id, difficulty=difficulty)
else:
flash(error)
return render_template('web/singlecharttop.html')
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@bp.route('/updatedatabase', methods=['GET', 'POST'])
@login_required
def update_database():
# 更新数据库
error = None
if request.method == 'POST':
if 'file' not in request.files:
flash('无文件 No file part.')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('未选择文件 No selected file.')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = 'old_' + secure_filename(file.filename)
file.save(os.path.join(UPLOAD_FOLDER, filename))
flash('上传成功 Success upload.')
try:
web.system.update_database()
flash('数据更新成功 Success update data.')
except:
flash('数据更新失败 Cannot update data.')
else:
error = '上传失败 Upload error.'
if error:
flash(error)
return render_template('web/updatedatabase.html')
@bp.route('/changesong', methods=['GET'])
@login_required
def change_song():
# 修改歌曲数据
return render_template('web/changesong.html')
@bp.route('/changesong/addsong', methods=['POST'])
@login_required
def add_song():
# 添加歌曲数据
def get_rating(x):
# 换算定数
if is_number(x):
x = float(x)
if x >= 0:
return int(x*10)
else:
return -1
else:
return -1
error = None
song_id = request.form['sid']
name_en = request.form['name_en']
rating_pst = get_rating(request.form['rating_pst'])
rating_prs = get_rating(request.form['rating_prs'])
rating_ftr = get_rating(request.form['rating_ftr'])
rating_byd = get_rating(request.form['rating_byd'])
if len(song_id) >= 256:
song_id = song_id[:200]
if len(name_en) >= 256:
name_en = name_en[:200]
conn = sqlite3.connect('./database/arcsong.db')
c = conn.cursor()
c.execute(
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
if c.fetchone() == (0,):
c.execute('''insert into songs(sid,name_en,rating_pst,rating_prs,rating_ftr,rating_byn) values(:a,:b,:c,:d,:e,:f)''', {
'a': song_id, 'b': name_en, 'c': rating_pst, 'd': rating_prs, 'e': rating_ftr, 'f': rating_byd})
flash('歌曲添加成功 Successfully add the song.')
else:
error = '歌曲已存在 The song exists.'
conn.commit()
conn.close()
if error:
flash(error)
return redirect(url_for('index.change_song'))
@bp.route('/changesong/deletesong', methods=['POST'])
@login_required
def delete_song():
# 删除歌曲数据
error = None
song_id = request.form['sid']
conn = sqlite3.connect('./database/arcsong.db')
c = conn.cursor()
c.execute(
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
if c.fetchone() == (1,):
c.execute('''delete from songs where sid=:a''', {'a': song_id})
flash('歌曲删除成功 Successfully delete the song.')
else:
error = "歌曲不存在 The song doesn't exist."
conn.commit()
conn.close()
if error:
flash(error)
return redirect(url_for('index.change_song'))

50
v1.3/web/login.py Normal file
View File

@@ -0,0 +1,50 @@
#import sqlite3
from flask import (Blueprint, flash, g, redirect,
render_template, request, session, url_for)
import functools
bp = Blueprint('login', __name__, url_prefix='/web')
@bp.route('/login', methods=('GET', 'POST'))
def login():
# 登录
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
error = None
if username != 'admin' and password != 'admin':
error = '错误的用户名或密码 Incorrect username or password.'
if error is None:
session.clear()
session['user_id'] = 'admin'
return redirect(url_for('index.index'))
flash(error)
return render_template('web/login.html')
@bp.route('/logout')
def logout():
# 登出
session.clear()
flash('成功登出 Successfully log out.')
return redirect(url_for('index.index'))
def login_required(view):
# 登录验证,写成了修饰器
@functools.wraps(view)
def wrapped_view(**kwargs):
x = session.get('user_id')
# 少用户存在验证
if x is None:
return redirect(url_for('login.login'))
g.user = {'user_id': x, 'username': 'admin'}
return view(**kwargs)
return wrapped_view

113
v1.3/web/system.py Normal file
View File

@@ -0,0 +1,113 @@
import os
import sqlite3
def update_user_char(c):
# 用character数据更新user_char
c.execute('''select * from character''')
x = c.fetchall()
c.execute('''select user_id from user''')
y = c.fetchall()
if x and y:
for j in y:
for i in x:
c.execute('''delete from user_char where user_id=:a and character_id=:b''', {
'a': j[0], 'b': i[0]})
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
'a': j[0], 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
def update_database():
# 将old数据库不存在数据加入到新数据库上并删除old数据库
# 对于arcaea_datebase.db更新best_scorefriendrecent30useruser_world并用character数据更新user_char
# 对于arcsong.db更新songs
if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"):
conn1 = sqlite3.connect('./database/old_arcaea_database.db')
c1 = conn1.cursor()
conn2 = sqlite3.connect('./database/arcaea_database.db')
c2 = conn2.cursor()
# user
c1.execute('''select * from user''')
x = c1.fetchall()
if x:
for i in x:
c2.execute(
'''select exists(select * from user where user_id=:a)''', {'a': i[0]})
if c2.fetchone() == (0,):
c2.execute('''insert into user values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25)''', {
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25]})
# friend
c1.execute('''select * from friend''')
x = c1.fetchall()
if x:
for i in x:
c2.execute(
'''select exists(select * from friend where user_id_me=:a and user_id_other=:b)''', {'a': i[0], 'b': i[1]})
if c2.fetchone() == (0,):
c2.execute('''insert into friend values(:a,:b)''', {
'a': i[0], 'b': i[1]})
# best_score
c1.execute('''select * from best_score''')
x = c1.fetchall()
if x:
for i in x:
c2.execute('''select exists(select * from best_score where user_id=:a and song_id=:b and difficulty=:c)''', {
'a': i[0], 'b': i[1], 'c': i[2]})
if c2.fetchone() == (0,):
c2.execute('''insert into best_score values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13)''', {
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13]})
# recent30
c1.execute('''select * from recent30''')
x = c1.fetchall()
if x:
for i in x:
c2.execute(
'''select exists(select * from recent30 where user_id=:a)''', {'a': i[0]})
if c2.fetchone() == (0,):
c2.execute('''insert into recent30 values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27,:a28,:a29,:a30,:a31,:a32,:a33,:a34,:a35,:a36,:a37,:a38,:a39,:a40,:a41,:a42,:a43,:a44,:a45,:a46,:a47,:a48,:a49,:a50,:a51,:a52,:a53,:a54,:a55,:a56,:a57,:a58,:a59,:a60)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[
18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27], 'a28': i[28], 'a29': i[29], 'a30': i[30], 'a31': i[31], 'a32': i[32], 'a33': i[33], 'a34': i[34], 'a35': i[35], 'a36': i[36], 'a37': i[37], 'a38': i[38], 'a39': i[39], 'a40': i[40], 'a41': i[41], 'a42': i[42], 'a43': i[43], 'a44': i[44], 'a45': i[45], 'a46': i[46], 'a47': i[47], 'a48': i[48], 'a49': i[49], 'a50': i[50], 'a51': i[51], 'a52': i[52], 'a53': i[53], 'a54': i[54], 'a55': i[55], 'a56': i[56], 'a57': i[57], 'a58': i[58], 'a59': i[59], 'a60': i[60]})
# user_world
c1.execute('''select * from user_world''')
x = c1.fetchall()
if x:
for i in x:
c2.execute(
'''select exists(select * from user_world where user_id=:a and map_id=:b)''', {'a': i[0], 'b': i[1]})
if c2.fetchone() == (0,):
c2.execute('''insert into user_world values(:a0,:a1,:a2,:a3,:a4)''', {
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4]})
update_user_char(c2)
conn1.commit()
conn1.close()
conn2.commit()
conn2.close()
os.remove('database/old_arcaea_database.db')
# songs
if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"):
conn1 = sqlite3.connect('./database/old_arcsong.db')
c1 = conn1.cursor()
conn2 = sqlite3.connect('./database/arcsong.db')
c2 = conn2.cursor()
c1.execute('''select * from songs''')
x = c1.fetchall()
if x:
for i in x:
c2.execute(
'''select exists(select * from songs where sid=:a)''', {'a': i[0]})
if c2.fetchone() == (0,):
c2.execute('''insert into songs values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[
8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27]})
conn1.commit()
conn1.close()
conn2.commit()
conn2.close()
os.remove('database/old_arcsong.db')

104
v1.3/web/webscore.py Normal file
View File

@@ -0,0 +1,104 @@
import time
def get_user_score(c, user_id, limit=-1):
# 返回用户的所有歌曲数据,带排名,返回字典列表
if limit >= 0:
c.execute('''select * from best_score where user_id =:a order by rating DESC limit :b''',
{'a': user_id, 'b': limit})
else:
c.execute(
'''select * from best_score where user_id =:a order by rating DESC''', {'a': user_id})
x = c.fetchall()
r = []
if x:
rank = 0
for i in x:
rank += 1
r.append({
"song_id": i[1],
"difficulty": i[2],
"score": i[3],
"shiny_perfect_count": i[4],
"perfect_count": i[5],
"near_count": i[6],
"miss_count": i[7],
"health": i[8],
"modifier": i[9],
"time_played": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(i[10])),
"best_clear_type": i[11],
"clear_type": i[12],
"rating": i[13],
"rank": rank
})
return r
def get_user(c, user_id):
# 得到user表部分用户信息返回字典
c.execute('''select * from user where user_id = :a''', {'a': user_id})
x = c.fetchone()
r = None
if x:
join_date = None
time_played = None
if x[3]:
join_date = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(int(x[3])//1000))
if x[20]:
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(int(x[20])//1000))
r = {'name': x[1],
'user_id': user_id,
'join_date': join_date,
'user_code': x[4],
'rating_ptt': x[5],
'song_id': x[11],
'difficulty': x[12],
'score': x[13],
'shiny_perfect_count': x[14],
'perfect_count': x[15],
'near_count': x[16],
'miss_count': x[17],
'time_played': time_played,
'clear_type': x[21],
'rating': x[22]
}
return r
def get_user_recent30(c, user_id):
# 获取玩家recent30信息并计算这一部分的ptt返回字典列表和一个值
c.execute('''select * from recent30 where user_id=:a''', {'a': user_id})
sumr = 0
x = c.fetchone()
r = []
if x is not None:
r30 = []
s30 = []
for i in range(1, 61, 2):
if x[i] is not None:
r30.append(float(x[i]))
s30.append(x[i+1])
else:
r30.append(0)
s30.append('')
r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True)))
songs = []
i = 0
while len(songs) < 10 and i <= 29 and s30[i] != '' and s30[i] is not None:
if s30[i] not in songs:
sumr += r30[i]
songs.append(s30[i])
i += 1
for i in range(0, 30):
if s30[i]:
r.append({
'song_id': s30[i][:-1],
'difficulty': int(s30[i][-1]),
'rating': r30[i]
})
return r, sumr / 10