11 Commits
v2.6 ... v2.7.0

Author SHA1 Message Date
Lost-MSth
d0be49fe20 Update to v2.7.0 2021-11-14 21:35:34 +08:00
Lost-MSth
b494b93c14 Update to v2.6.6 without release
- Fix a bug about purchase discount
- Fix a bug about database synchronization, which may make 'api_login' table empty
- For Arcaea 3.8.8
- Update a logout api
2021-10-22 20:00:22 +08:00
Lost-MSth
a523ff5aae Update README.md
Add some download links.

close #28
2021-10-01 16:24:56 +08:00
Lost-MSth
acbe9fc4a1 Merge pull request #31 from superDXZ/master
Try to add some download links.
2021-10-01 16:19:53 +08:00
superDXZ
9422bf7182 Update README.md
Found another download site
2021-10-01 02:49:06 +08:00
superDXZ
53acad4ffb Update README.md
Found another download site
2021-10-01 02:46:39 +08:00
Lost-MSth
13048e57f4 Update to v2.6.5 without release
- Change something to make that purchase things can have some cores.
- Fix the download link of Arcaea client in README

> This is a small update.
2021-09-30 19:02:10 +08:00
Lost-MSth
39d3f073ba Update to v2.6.4 without release 2021-09-08 17:35:10 +08:00
Lost-MSth
2cf6595478 Update to v2.6.3 2021-08-25 14:31:06 +08:00
Lost-MSth
7c3bc99570 Update to v2.6.2 2021-08-11 18:45:32 +08:00
Lost-MSth
168e5f0b12 Update to v2.6.1 2021-07-21 18:14:26 +08:00
22 changed files with 2523 additions and 1216 deletions

View File

@@ -53,7 +53,9 @@ It is just so interesting. What it can do is under exploration.
## 下载 Download
[这里 Here](https://github.com/Lost-MSth/Arcaea-server/releases)
[Arcaea](https://konmai.cn/#arcaea)
[Arcaea-CN official](https://arcaea.lowiro.com/zh)
[Arcaea-lowi.ro](https://lowi.ro)
[Arcaea-RhyDown](https://rhydown.com)
## 更新日志 Update log
只保留最新版本 Only keep the latest version.
@@ -62,19 +64,25 @@ It is just so interesting. What it can do is under exploration.
>
> Tips: When updating, please keep the original database in case of data loss.
### Version 2.6
- 适用于Arcaea 3.6.4版本 For Arcaea 3.6.4
### Version 2.7.0
- 适用于Arcaea 3.9.0版本 For Arcaea 3.9.0
- 更新了歌曲数据库 Update the song database.
-增体力系统 Add stamina system.
- 完善了登陆奖励系统 Improve the login present system.
- 完善了兑换码系统 Improve the redeem code system.
- 新增了多设备自动封号机制 Add multi device auto ban mechanism.
- 修复了一些Bug Fix some bugs.
- 修复好友列表没有按照最近成绩日期排序的问题(Menci) Fix the friend list not sorted by last score date. (From Menci)
- 修复某些情况下跨目录运行失败的问题(MBRjun) Fix cross directory running problem in some cases. (From MBRjun)
-搭档 **爱丽丝 & 坦尼尔(小步舞曲)** 已解锁 Unlock the new character **Alice & Tenniel (Minuet)**.
- 新搭档 **对立(挽歌)** 已解锁 Unlock the new character **Tairitsu (Elegy)**.
- 搭档 **爱托** 已觉醒 Uncap the character **Eto**.
- 搭档 **露娜** 已觉醒 Uncap the character **Luna**.
- 新增爱托和露娜的觉醒技能(可能有问题) Add the uncapped skills of Eto and Luna (There may be bugs.).
- 新增是否同步角色表的设置选项 Add the setting option of whether updating the character table.
- 以下是累积更新 The following are cumulative updates:
- 添加购买物品含有以太之滴的支持 Add support for purchasing items containing generic cores.
- 修复关于购买物品打折的问题 Fix a bug about purchase discount.
- 修复关于数据库同步的问题这可能导致api_login表为空 Fix a bug about database synchronization, which may make 'api_login' table empty.
- 新增登出API接口 Update a logout API.
> 提示:某些数据可能尚不完整,某个单曲的解锁和某两个角色的数据可能会有问题
> Tips: Some data may not be complete, so there may be problems with the unlocking of a single song and the data of two characters.
> 提醒使用新版本前可能需要清空redeemuser_redeempresentuser_present表
> Tips: Before using the new version, you may need to clear the redeem, user_redeem, present, user_present table.
## 运行环境与依赖 Running environment and requirements
- Windows/Linux/Mac OS/Android

View File

@@ -1,5 +1,7 @@
import hashlib
import base64
import time
import random
from server.sql import Connect
import functools
from setting import Config
@@ -14,14 +16,50 @@ class User():
self.power = power
def login():
# 登录接口
return {'token': 1}, 0
def login(auth: str, ip: str):
# 登录接口,返回字典和错误码
try:
auth_decode = bytes.decode(base64.b64decode(auth))
except:
return {}, -100
if not ':' in auth_decode:
return {}, -100
name, password = auth_decode.split(':', 1)
with Connect() as c:
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
c.execute('''select user_id, password from user where name = :name''', {
'name': name})
x = c.fetchone()
if x is None:
return {}, -201
if x[1] == '':
return {}, -202
if hash_pwd != x[1]:
return {}, -201
user_id = str(x[0])
now = int(time.time() * 1000)
token = hashlib.sha256(
(user_id + str(random.randint(10000, 99999)) + str(now)).encode("utf8")).hexdigest()
c.execute('''delete from api_login where user_id=?''', (user_id,))
c.execute('''insert into api_login values(?,?,?,?)''',
(user_id, token, now, ip))
return {'token': token, 'user_id': user_id}, 0
def logout():
# 登出接口
pass
def logout(user: User):
# 登出接口,返回错误码
code = 999
with Connect() as c:
c.execute('''delete from api_login where user_id=?''', (user.user_id,))
code = 0
return code
def id_get_role_id(c, user_id):
@@ -86,7 +124,7 @@ def role_required(request, power=[]):
return jsonify({'status': 400, 'code': -1, 'data': {}, 'msg': 'Payload must be a valid json'})
if not 'Token' in request.headers:
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No Token'})
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No token'})
user = User()
if Config.API_TOKEN == request.headers['Token'] and Config.API_TOKEN != '':
@@ -98,7 +136,7 @@ def role_required(request, power=[]):
user.user_id = api_token_get_id(
c, request.headers['Token'])
if user.user_id is None:
return jsonify({'status': 404, 'code': -1, 'data': {}, 'msg': ''})
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No token'})
role_id = id_get_role_id(c, user.user_id)
user.role = role_id_get_role(c, role_id)

View File

@@ -6,10 +6,14 @@ def code_get_msg(code):
'-2': 'No data',
'-3': 'No data or user',
'-4': 'No user_id',
'-100': 'Wrong post data',
'-101': 'Wrong data type',
'-102': 'Wrong query parameter',
'-103': 'Wrong sort parameter',
'-104': 'Wrong sort order parameter'
'-104': 'Wrong sort order parameter',
'-201': 'Wrong username or password',
'-202': 'User is banned',
'-999': 'Unknown error'
}
return msg[str(code)]

View File

@@ -1,6 +1,7 @@
from flask import (
Blueprint, request, jsonify
)
import functools
import api.api_auth
import api.users
import api.songs
@@ -10,93 +11,112 @@ from api.api_code import code_get_msg
bp = Blueprint('api', __name__, url_prefix='/api/v1')
class Query():
# 查询类,当查询附加参数的数据类型用
def __init__(self, limit=-1, offset=0, query={}, sort=[]) -> None:
self.limit = limit
self.offset = offset
self.query = query # {'name': 'admin'}
self.sort = sort # [{'column': 'user_id', 'order': 'ASC'}, ...]
def get_query_parameter(request, query_able=[], sort_able=[]):
# 提取查询请求参数,返回四个参数和code
# 提取查询请求参数,返回Query类查询参数写成修饰器
limit = -1
offset = 0
query = {} # {'name': 'admin'}
sort = [] # [{'column': 'user_id', 'order': 'ASC'}, ...]
def decorator(view):
@functools.wraps(view)
def wrapped_view(*args, **kwargs):
if 'limit' in request.json:
try:
limit = int(request.json['limit'])
except:
return -1, 0, {}, {}, -101
if 'offset' in request.json:
try:
offset = int(request.json['offset'])
except:
return -1, 0, {}, {}, -101
if 'query' in request.json:
query = request.json['query']
for i in query:
if i not in query_able:
return -1, 0, {}, {}, -102
if 'sort' in request.json:
sort = request.json['sort']
for i in sort:
if 'column' not in i or i['column'] not in sort_able:
return -1, 0, {}, {}, -103
if not 'order' in i:
i['order'] = 'ASC'
else:
if i['order'] not in ['ASC', 'DESC']:
return -1, 0, {}, {}, -104
re = Query()
return limit, offset, query, sort, 0
if 'limit' in request.json:
try:
re.limit = int(request.json['limit'])
except:
return jsonify({'status': 200, 'code': -101, 'data': {}, 'msg': code_get_msg(-101)})
if 'offset' in request.json:
try:
re.offset = int(request.json['offset'])
except:
return jsonify({'status': 200, 'code': -101, 'data': {}, 'msg': code_get_msg(-101)})
if 'query' in request.json:
re.query = request.json['query']
for i in re.query:
if i not in query_able:
return jsonify({'status': 200, 'code': -102, 'data': {}, 'msg': code_get_msg(-102)})
if 'sort' in request.json:
re.sort = request.json['sort']
for i in re.sort:
if 'column' not in i or i['column'] not in sort_able:
return jsonify({'status': 200, 'code': -103, 'data': {}, 'msg': code_get_msg(-103)})
if not 'order' in i:
i['order'] = 'ASC'
else:
if i['order'] not in ['ASC', 'DESC']:
return jsonify({'status': 200, 'code': -104, 'data': {}, 'msg': code_get_msg(-104)})
return view(re, *args, **kwargs)
return wrapped_view
return decorator
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
# 构造返回返回jsonify处理过后的response_class
if msg == '':
msg = code_get_msg(code)
if code < 0:
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
else:
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})
@bp.route('/')
def ping():
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
return return_encode()
@bp.route('/token', methods=['POST'])
def token_post():
# 登录获取token
# {'auth': `base64(user_id:password)`}
if 'auth' in request.json:
data, code = api.api_auth.login(
request.json['auth'], request.remote_addr)
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
else:
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
str(request.json['auth']), request.remote_addr)
return return_encode(code, data)
else:
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No authentication'})
return return_encode(-1, {}, 401, 'No authentication')
@bp.route('/token', methods=['GET'])
@api.api_auth.role_required(request, ['select_me', 'select'])
def token_get(user):
# 判断登录有效性
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
return return_encode()
@bp.route('/token', methods=['DELETE'])
@api.api_auth.role_required(request, ['change_me', 'select_me', 'select'])
def token_delete(user):
# 登出
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
return return_encode(api.api_auth.logout(user))
@bp.route('/users', methods=['GET'])
@api.api_auth.role_required(request, ['select'])
def users_get(user):
@get_query_parameter(request, ['user_id', 'name', 'user_code'], [
'user_id', 'name', 'user_code', 'join_date', 'rating_ptt', 'time_played', 'ticket', 'world_rank_score'])
def users_get(query, user):
# 查询全用户信息
limit, offset, query, sort, code = get_query_parameter(request, ['user_id', 'name', 'user_code'], [
'user_id', 'name', 'user_code', 'join_date', 'rating_ptt', 'time_played', 'ticket', 'world_rank_score'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.users.get_users(limit, offset, query, sort)
data = api.users.get_users(query)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>', methods=['GET'])
@@ -108,17 +128,17 @@ def users_user_get(user, user_id):
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
return return_encode(-4)
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_info(user_id)
if not data:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>/b30', methods=['GET'])
@@ -126,48 +146,39 @@ def users_user_get(user, user_id):
def users_user_b30_get(user, user_id):
# 查询用户b30
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
return return_encode(-4)
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_b30(user_id)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>/best', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_me'])
def users_user_best_get(user, user_id):
@get_query_parameter(request, ['song_id', 'difficulty'], [
'song_id', 'difficulty', 'score', 'time_played', 'rating'])
def users_user_best_get(query, user, user_id):
# 查询用户所有best成绩
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
return return_encode(-4)
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
return return_encode(-1, {}, 403, 'No permission')
limit, offset, query, sort, code = get_query_parameter(request, ['song_id', 'difficulty'], [
'song_id', 'difficulty', 'score', 'time_played', 'rating'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.users.get_user_best(user_id, limit, offset, query, sort)
data = api.users.get_user_best(user_id, query)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>/r30', methods=['GET'])
@@ -175,21 +186,18 @@ def users_user_best_get(user, user_id):
def users_user_r30_get(user, user_id):
# 查询用户r30
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
return return_encode(-4)
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
return return_encode(-1, {}, 403, 'No permission')
data = api.users.get_user_r30(user_id)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/songs/<string:song_id>', methods=['GET'])
@@ -200,24 +208,21 @@ def songs_song_get(user, song_id):
data = api.songs.get_song_info(song_id)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/songs', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_song_info'])
def songs_get(user):
@get_query_parameter(request, ['sid', 'name_en', 'name_jp', 'pakset', 'artist'], [
'sid', 'name_en', 'name_jp', 'pakset', 'artist', 'date', 'rating_pst', 'rating_prs', 'rating_ftr', 'rating_byn'])
def songs_get(query, user):
# 查询全歌曲信息
limit, offset, query, sort, code = get_query_parameter(request, ['sid', 'name_en', 'name_jp', 'pakset', 'artist'], [
'sid', 'name_en', 'name_jp', 'pakset', 'artist', 'date', 'rating_pst', 'rating_prs', 'rating_ftr', 'rating_byn'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.songs.get_songs(limit, offset, query, sort)
data = api.songs.get_songs(query)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)

View File

@@ -30,12 +30,12 @@ def get_song_info(song_id):
return r
def get_songs(limit=-1, offset=0, query={}, sort=[]):
def get_songs(query=None):
# 查询全部歌曲信息,返回字典列表
r = []
with Connect('./database/arcsong.db') as c:
x = Sql.select(c, 'songs', [], limit, offset, query, sort)
x = Sql.select(c, 'songs', [], query)
if x:
for i in x:

View File

@@ -5,12 +5,12 @@ import web.webscore
import server.info
def get_users(limit=-1, offset=0, query={}, sort=[]):
def get_users(query=None):
# 获取全用户信息,返回字典列表
r = []
with Connect() as c:
x = Sql.select(c, 'user', [], limit, offset, query, sort)
x = Sql.select(c, 'user', [], query)
if x:
for i in x:
@@ -62,12 +62,12 @@ def get_user_b30(user_id):
return {'user_id': user_id, 'b30_ptt': bestptt / 30, 'data': r}
def get_user_best(user_id, limit=-1, offset=0, query={}, sort=[]):
def get_user_best(user_id, query=None):
# 获取用户b30信息返回字典
r = []
with Connect() as c:
x = Sql.select(c, 'best_score', [], limit, offset, query, sort)
x = Sql.select(c, 'best_score', [], query)
if x:
for i in x:
r.append({

Binary file not shown.

View File

@@ -4,7 +4,7 @@ import json
# 数据库初始化文件删掉arcaea_database.db文件后运行即可谨慎使用
ARCAEA_SERVER_VERSION = 'v2.6'
ARCAEA_SERVER_VERSION = 'v2.7.0'
def main(path='./'):
@@ -228,6 +228,7 @@ def main(path='./'):
c.execute('''create table if not exists purchase_item(purchase_name text,
item_id text,
type text,
amount int,
primary key(purchase_name, item_id, type)
);''')
c.execute('''create table if not exists user_save(user_id int primary key,
@@ -298,46 +299,46 @@ def main(path='./'):
# 搭档初始化
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)', 'etude', 'Alice & Tenniel', 'Luna & Mia', 'areus', 'seele', 'isabelle', 'mir', 'lagrange', '???', 'nami']
'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)', 'etude', 'Alice & Tenniel', 'Luna & Mia', 'areus', 'seele', 'isabelle', 'mir', 'lagrange', 'linka', 'nami', 'Saya & Elizabeth', 'lily', 'kanae(midsummer)', 'alice&tenniel(minuet)', 'tairitsu(elegy)']
skill_id = ['gauge_easy', '', '', '', 'note_mirror', '', '', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami']
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily', 'skill_kanae_midsummer', '', '']
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', 'eto_uncap', 'luna_uncap', 'shirabe_entry_fee',
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
skill_unlock_level = [0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0,
0, 0, 0, 8, 0, 14, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]
0, 0, 0, 8, 0, 14, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
frag1 = [55, 55, 60, 50, 47, 0, 47, 57, 41, 22, 50, 54, 60, 56, 78, 42, 41, 61, 52, 50, 52, 32,
42, 55, 45, 58, 43, 0.5, 68, 50, 62, 45, 45, 52, 44, 27, 59, 0, 45, 50, 50, 47, 47, 61, 43, 42, 50, 25]
42, 55, 45, 58, 43, 0.5, 68, 50, 62, 45, 45, 52, 44, 27, 59, 0, 45, 50, 50, 47, 47, 61, 43, 42, 50, 25, 58, 50, 61, 55, 55]
prog1 = [35, 55, 47, 50, 60, 0, 60, 70, 58, 45, 70, 45, 42, 46, 61, 67, 49, 44, 28, 45, 24, 46, 52,
59, 62, 33, 58, 25, 63, 69, 50, 45, 45, 51, 34, 70, 62, 70, 45, 32, 32, 61, 47, 47, 37, 42, 50, 50]
59, 62, 33, 58, 25, 63, 69, 50, 45, 45, 51, 34, 70, 62, 70, 45, 32, 32, 61, 47, 47, 37, 42, 50, 50, 45, 41, 61, 55, 55]
overdrive1 = [35, 55, 25, 50, 47, 0, 72, 57, 41, 7, 10, 32, 65, 31, 61, 53, 31, 47, 38, 12, 39, 18,
48, 65, 45, 55, 44, 25, 46, 44, 33, 45, 45, 37, 25, 27, 50, 20, 45, 63, 21, 47, 61, 47, 65, 80, 50, 30]
48, 65, 45, 55, 44, 25, 46, 44, 33, 45, 45, 37, 25, 27, 50, 20, 45, 63, 21, 47, 61, 47, 65, 80, 50, 30, 49, 15, 34, 55, 55]
frag20 = [78, 80, 90, 75, 70, 0, 70, 79, 65, 40, 50, 80, 90, 82, 0, 61, 67, 92, 85, 50, 86, 52,
65, 85, 67, 88, 64, 0.5, 95, 70, 95, 50, 80, 87, 71, 50, 85, 0, 80, 75, 50, 70, 70, 90, 65, 80, 100, 50]
65, 85, 67, 88, 64, 0.5, 95, 70, 95, 50, 80, 87, 71, 50, 85, 0, 80, 75, 50, 70, 70, 90, 65, 80, 100, 50, 68, 60, 90, 80, 80]
prog20 = [61, 80, 70, 75, 90, 0, 90, 102, 84, 78, 105, 67, 63, 68, 0, 99, 80, 66, 46, 83, 40, 73,
80, 90, 93, 50, 86, 78, 89, 98, 75, 80, 50, 64, 55, 100, 90, 110, 80, 50, 74, 90, 70, 70, 56, 80, 100, 55]
80, 90, 93, 50, 86, 78, 89, 98, 75, 80, 50, 64, 55, 100, 90, 110, 80, 50, 74, 90, 70, 70, 56, 80, 100, 55, 65, 59, 90, 80, 80]
overdrive20 = [61, 80, 47, 75, 70, 0, 95, 79, 65, 31, 50, 59, 90, 58, 0, 78, 50, 70, 62, 49, 64,
46, 73, 95, 67, 84, 70, 78, 69, 70, 50, 80, 80, 63, 25, 50, 72, 55, 50, 95, 55, 70, 90, 70, 99, 80, 100, 40]
46, 73, 95, 67, 84, 70, 78, 69, 70, 50, 80, 80, 63, 25, 50, 72, 55, 50, 95, 55, 70, 90, 70, 99, 80, 100, 40, 69, 62, 51, 80, 80]
frag30 = [88, 90, 100, 75, 80, 0, 70, 79, 65, 40, 50, 80, 90, 92, 0, 61, 67, 92, 85, 50, 86, 62,
65, 85, 67, 88, 74, 0.5, 105, 80, 95, 50, 80, 87, 71, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 100, 50]
frag30 = [88, 90, 100, 75, 80, 0, 70, 79, 65, 40, 50, 90, 100, 92, 0, 61, 67, 92, 85, 50, 86, 62,
65, 85, 67, 88, 74, 0.5, 105, 80, 95, 50, 80, 87, 71, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 100, 50, 68, 60, 90, 80, 80]
prog30 = [71, 90, 80, 75, 100, 0, 90, 102, 84, 78, 105, 67, 63, 78, 0, 99, 80, 66, 46, 83, 40, 83,
80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 100, 55]
prog30 = [71, 90, 80, 75, 100, 0, 90, 102, 84, 78, 105, 77, 73, 78, 0, 99, 80, 66, 46, 83, 40, 83,
80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 100, 55, 65, 59, 90, 80, 80]
overdrive30 = [71, 90, 57, 75, 80, 0, 95, 79, 65, 31, 50, 59, 90, 68, 0, 78, 50, 70, 62, 49, 64,
56, 73, 95, 67, 84, 80, 88, 79, 80, 50, 80, 80, 63, 25, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 100, 40]
overdrive30 = [71, 90, 57, 75, 80, 0, 95, 79, 65, 31, 50, 69, 100, 68, 0, 78, 50, 70, 62, 49, 64,
56, 73, 95, 67, 84, 80, 88, 79, 80, 50, 80, 80, 63, 25, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 100, 40, 69, 62, 51, 80, 80]
char_type = [1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, 2, 3, 1, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1, 0, 0, 0]
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0]
char_core = {
0: [{'core_id': 'core_hollow', 'amount': 25}, {'core_id': 'core_desolate', 'amount': 5}],
@@ -352,13 +353,15 @@ def main(path='./'):
29: [{'core_id': 'core_chunithm', 'amount': 15}],
36: [{'core_id': 'core_chunithm', 'amount': 15}],
42: [{'core_id': 'core_chunithm', 'amount': 15}],
43: [{'core_id': 'core_chunithm', 'amount': 15}]
43: [{'core_id': 'core_chunithm', 'amount': 15}],
11: [{'core_id': 'core_binary', 'amount': 25}, {'core_id': 'core_hollow', 'amount': 5}],
12: [{'core_id': 'core_binary', 'amount': 25}, {'core_id': 'core_desolate', 'amount': 5}]
}
for i in range(0, 48):
for i in range(0, 53):
skill_requires_uncap = 1 if i == 2 else 0
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43, 11, 12]:
sql = '''insert into character values(?,?,30,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1)'''
c.execute(sql, (i, char[i], frag1[i], prog1[i], overdrive1[i], frag20[i], prog20[i], overdrive20[i],
frag30[i], prog30[i], overdrive30[i], skill_id[i], skill_unlock_level[i], skill_requires_uncap, skill_id_uncap[i], char_type[i]))
@@ -373,13 +376,13 @@ def main(path='./'):
c.execute('''insert into char_item values(?,?,'core',?)''',
(i, j['core_id'], j['amount']))
cores = ['core_hollow', 'core_desolate', 'core_chunithm', 'core_crimson',
'core_ambivalent', 'core_scarlet', 'core_groove', 'core_generic']
'core_ambivalent', 'core_scarlet', 'core_groove', 'core_generic', 'core_binary']
for i in cores:
c.execute('''insert into item values(?,"core",1,'')''', (i,))
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", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3"]
"cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3", "kyogenkigo", "hivemind", "seclusion", "quonwacca3", "bluecomet", "energysynergymatrix", "gengaozo", "lastendconductor3"]
for i in world_songs:
c.execute('''insert into item values(?,"world_song",1,'')''', (i,))
@@ -411,10 +414,17 @@ def main(path='./'):
_id = ''
else:
_id = j['_id']
c.execute('''insert into item values(?,?,?,?)''',
(j['id'], j['type'], j['is_available'], _id))
c.execute('''insert into purchase_item values(?,?,?)''',
(i['name'], j['id'], j['type']))
c.execute(
'''select exists(select * from item where item_id=?)''', (j['id'],))
if c.fetchone() == (0,):
c.execute('''insert into item values(?,?,?,?)''',
(j['id'], j['type'], j['is_available'], _id))
if 'amount' in j:
amount = j['amount']
else:
amount = 1
c.execute('''insert into purchase_item values(?,?,?,?)''',
(i['name'], j['id'], j['type'], amount))
# item初始化
f = open(path+'singles.json', 'r')

View File

@@ -0,0 +1,376 @@
{
"map_id": "byd_bookmaker",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "bookmaker2",
"require_type": "chart_unlock",
"coordinate": "-650,-650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 300,
"character_affinity": [
23,
34,
47
],
"affinity_multiplier": [
1.3,
5,
3.8
],
"step_count": 31,
"custom_bg": "",
"curr_position": 3,
"curr_capture": 35.81730523472207,
"is_locked": false,
"steps": [
{
"map_id": "byd_bookmaker",
"position": 0,
"capture": 10
},
{
"map_id": "byd_bookmaker",
"position": 1,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 2,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 3,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
],
"restrict_ids": [
"bookmaker",
"viciousheroism",
"battlenoone",
"galaxyfriends",
"rekkaresonance"
],
"restrict_type": "song_id"
},
{
"map_id": "byd_bookmaker",
"position": 4,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 5,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 6,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 7,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 8,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 9,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 10,
"capture": 10,
"items": [
{
"type": "core",
"id": "core_generic",
"amount": 1
}
]
},
{
"map_id": "byd_bookmaker",
"position": 11,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 12,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 13,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 14,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 15,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 16,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 17,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 18,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 19,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 20,
"capture": 10,
"items": [
{
"type": "core",
"id": "core_generic",
"amount": 1
}
]
},
{
"map_id": "byd_bookmaker",
"position": 21,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 22,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 23,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 24,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 25,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 26,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 27,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 28,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 29,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 30,
"capture": 0,
"items": [
{
"id": "bookmaker3",
"type": "world_song"
}
]
}
]
}

View File

@@ -1,250 +1,515 @@
[{
"name": "core",
"items": [{
"type": "pack",
"id": "core",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "shiawase",
"items": [{
"type": "pack",
"id": "shiawase",
"is_available": true
}, {
"type": "character",
"id": "kou",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "dynamix",
"items": [{
"type": "pack",
"id": "dynamix",
"is_available": true
}, {
"type": "character",
"id": "sapphire",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "mirai",
"items": [{
"type": "pack",
"id": "mirai",
"is_available": true
}, {
"type": "character",
"id": "lethe",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "yugamu",
"items": [{
"type": "pack",
"id": "yugamu",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "lanota",
"items": [{
"type": "pack",
"id": "lanota",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "nijuusei",
"items": [{
"type": "pack",
"id": "nijuusei",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "rei",
"items": [{
"type": "pack",
"id": "rei",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "tonesphere",
"items": [{
"type": "pack",
"id": "tonesphere",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "groovecoaster",
"items": [{
"type": "pack",
"id": "groovecoaster",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "zettai",
"items": [{
"type": "pack",
"id": "zettai",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "chunithm",
"items": [{
"type": "pack",
"id": "chunithm",
"is_available": true
}],
"price": 300,
"orig_price": 300
}, {
"name": "prelude",
"items": [{
"type": "pack",
"id": "prelude",
"is_available": true
}],
"price": 400,
"orig_price": 400,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "omatsuri",
"items": [{
"type": "pack",
"id": "omatsuri",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "vs",
"items": [{
"type": "pack",
"id": "vs",
"is_available": true
}],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "extend",
"items": [{
"type": "pack",
"id": "extend",
"is_available": true
}],
"price": 700,
"orig_price": 700,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, {
"name": "alice",
"items": [{
"type": "pack",
"id": "alice",
"is_available": true
}],
"orig_price": 500,
"price": 500
}, {
"name": "alice_append_1",
"items": [{
"type": "pack",
"id": "alice_append_1",
"is_available": true
}],
"orig_price": 300,
"price": 300
}, {
"name": "ongeki",
"items": [{
"type": "pack",
"id": "ongeki",
"is_available": true
}],
"orig_price": 400,
"price": 400
}, {
"name": "maimai",
"items": [{
"type": "pack",
"id": "maimai",
"is_available": true
}],
"orig_price": 400,
"price": 400
}, {
"name": "chunithm_append_1",
"items": [{
"type": "pack",
"id": "chunithm_append_1",
"is_available": true
}],
"orig_price": 300,
"price": 300
}, {
"name": "observer_append_1",
"items": [{
"type": "pack",
"id": "observer_append_1",
"is_available": true
}],
"orig_price": 300,
"price": 300
}, {
"name": "observer",
"items": [{
"type": "pack",
"id": "observer",
"is_available": true
}],
"orig_price": 500,
"price": 500
}]
[
{
"name": "core",
"items": [
{
"type": "pack",
"id": "core",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "shiawase",
"items": [
{
"type": "pack",
"id": "shiawase",
"is_available": true
},
{
"type": "character",
"id": "kou",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "dynamix",
"items": [
{
"type": "pack",
"id": "dynamix",
"is_available": true
},
{
"type": "character",
"id": "sapphire",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "mirai",
"items": [
{
"type": "pack",
"id": "mirai",
"is_available": true
},
{
"type": "character",
"id": "lethe",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "yugamu",
"items": [
{
"type": "pack",
"id": "yugamu",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "lanota",
"items": [
{
"type": "pack",
"id": "lanota",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "nijuusei",
"items": [
{
"type": "pack",
"id": "nijuusei",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "rei",
"items": [
{
"type": "pack",
"id": "rei",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "tonesphere",
"items": [
{
"type": "pack",
"id": "tonesphere",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "groovecoaster",
"items": [
{
"type": "pack",
"id": "groovecoaster",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "zettai",
"items": [
{
"type": "pack",
"id": "zettai",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "chunithm",
"items": [
{
"type": "pack",
"id": "chunithm",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"price": 300,
"orig_price": 300
},
{
"name": "prelude",
"items": [
{
"type": "pack",
"id": "prelude",
"is_available": true
},
{
"type": "core",
"amount": 4,
"id": "core_generic",
"is_available": true
}
],
"price": 400,
"orig_price": 400,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "omatsuri",
"items": [
{
"type": "pack",
"id": "omatsuri",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "vs",
"items": [
{
"type": "pack",
"id": "vs",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"price": 500,
"orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "extend",
"items": [
{
"type": "pack",
"id": "extend",
"is_available": true
},
{
"type": "core",
"amount": 7,
"id": "core_generic",
"is_available": true
}
],
"price": 0,
"orig_price": 700,
"discount_from": 1615248000000,
"discount_to": 1615852799000
},
{
"name": "alice",
"items": [
{
"type": "pack",
"id": "alice",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 500,
"price": 500
},
{
"name": "alice_append_1",
"items": [
{
"type": "pack",
"id": "alice_append_1",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 300,
"price": 300
},
{
"name": "ongeki",
"items": [
{
"type": "pack",
"id": "ongeki",
"is_available": true
},
{
"type": "core",
"amount": 4,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 400,
"price": 400
},
{
"name": "maimai",
"items": [
{
"type": "pack",
"id": "maimai",
"is_available": true
},
{
"type": "core",
"amount": 4,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 400,
"price": 400
},
{
"name": "chunithm_append_1",
"items": [
{
"type": "pack",
"id": "chunithm_append_1",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 300,
"price": 300
},
{
"name": "observer_append_1",
"items": [
{
"type": "pack",
"id": "observer_append_1",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 300,
"price": 300
},
{
"name": "observer",
"items": [
{
"type": "pack",
"id": "observer",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 500,
"price": 500
},
{
"name": "observer_append_2",
"items": [
{
"type": "pack",
"id": "observer_append_2",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 300,
"price": 300
},
{
"name": "wacca",
"items": [
{
"type": "pack",
"id": "wacca",
"is_available": true
},
{
"type": "core",
"amount": 5,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 500,
"price": 500
},
{
"name": "nijuusei_append_1",
"items": [
{
"type": "pack",
"id": "nijuusei_append_1",
"is_available": true
},
{
"type": "core",
"amount": 3,
"id": "core_generic",
"is_available": true
}
],
"orig_price": 300,
"price": 300
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -251,6 +251,15 @@ def aggregate(user_id):
return jsonify(r)
@app.route(add_url_prefix('/user/me'), methods=['GET']) # 用户信息给baa查分器用的
@server.auth.auth_required(request)
def user_me(user_id):
r = server.info.arc_aggregate_small(user_id)
if r['success']:
r['value'] = r['value'][0]['value']
return jsonify(r)
@app.route(add_url_prefix('/user/me/character'), methods=['POST']) # 角色切换
@server.auth.auth_required(request)
def character_change(user_id):
@@ -623,7 +632,7 @@ def world_all(user_id):
})
@app.route(add_url_prefix('/world/map/me/'), methods=['POST']) # 进入地图
@app.route(add_url_prefix('/world/map/me'), methods=['POST']) # 进入地图
@server.auth.auth_required(request)
def world_in(user_id):
map_id = request.form['map_id']

View File

@@ -25,15 +25,35 @@ def get_purchase(c, type='pack'):
for i in x:
items = []
c.execute(
'''select a.* from item a, purchase_item b where a.item_id=b.item_id and a.type=b.type and b.purchase_name=:name''', {'name': i[0]})
'''select a.*, b.amount from item a, purchase_item b where a.item_id=b.item_id and a.type=b.type and b.purchase_name=:name''', {'name': i[0]})
y = c.fetchall()
t = None
if y:
for j in y:
items.append({
"type": j[1],
"id": j[0],
"is_available": int2b(j[2])
})
if j[3]:
amount = j[3]
else:
amount = 1
if i[0] == j[0]:
# 物品排序,否则客户端报错
t = {
"type": j[1],
"id": j[0],
"is_available": int2b(j[2]),
'amount': amount
}
else:
items.append({
"type": j[1],
"id": j[0],
"is_available": int2b(j[2]),
"amount": amount
})
if t is not None:
# 放到列表头
items = [t, items]
r = {"name": i[0],
"items": items,
@@ -104,7 +124,7 @@ def buy_thing(user_id, purchase_id):
}
c.execute(
'''select item_id, type from purchase_item where purchase_name=:a''', {'a': purchase_id})
'''select item_id, type, amount from purchase_item where purchase_name=:a''', {'a': purchase_id})
x = c.fetchall()
if x:
now = int(time.time() * 1000)
@@ -115,7 +135,11 @@ def buy_thing(user_id, purchase_id):
if flag:
for i in x:
server.item.claim_user_item(c, user_id, i[0], i[1])
if i[2]:
amount = i[2]
else:
amount = 1
server.item.claim_user_item(c, user_id, i[0], i[1], amount)
success_flag = True
else:

View File

@@ -286,7 +286,8 @@ def get_user_ptt_float(c, user_id) -> float:
if x != []:
for i in x:
sumr += float(i[0])
c.execute('''select * from recent30 where user_id = :a''', {'a': user_id})
c.execute('''select * from recent30 where user_id = :a''',
{'a': user_id})
x = c.fetchone()
if x is not None:
r30 = []
@@ -298,7 +299,8 @@ def get_user_ptt_float(c, user_id) -> float:
else:
r30.append(0)
s30.append('')
r30, s30 = (list(t) for t in zip(*sorted(zip(r30, s30), reverse=True)))
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:
@@ -882,6 +884,36 @@ def arc_all_get(user_id):
"mi": 6,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 1,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 2,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 3,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 4,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 5,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 6,
"c": True,
"r": True
}, {
"ma": 9,
"mi": 1,
@@ -913,50 +945,50 @@ def arc_all_get(user_id):
"c": True,
"r": True
}, {
"ma": 6,
"ma": 10,
"mi": 1,
"c": True,
"r": True
}, {
"ma": 6,
"ma": 10,
"mi": 2,
"c": True,
"r": True
}, {
"ma": 6,
"ma": 10,
"mi": 3,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 1,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 2,
"c": True,
"r": True
}, {
"ma": 7,
"mi": 3,
"c": True,
"r": True
}, {
"ma": 7,
"ma": 10,
"mi": 4,
"c": True,
"r": True
}, {
"ma": 7,
"ma": 10,
"mi": 5,
"c": True,
"r": True
}, {
"ma": 7,
"ma": 10,
"mi": 6,
"c": True,
"r": True
}, {
"ma": 6,
"mi": 1,
"c": True,
"r": True
}, {
"ma": 6,
"mi": 2,
"c": True,
"r": True
}, {
"ma": 6,
"mi": 3,
"c": True,
"r": True
}, {
"ma": 8,
"mi": 1,
@@ -979,42 +1011,30 @@ def arc_all_get(user_id):
}, {
"unlock_key": "worldexecuteme|2|0",
"complete": 1
}, {
"unlock_key": "viyellastears|2|0",
"complete": 1
}, {
"unlock_key": "viciousheroism|2|0",
"complete": 1
}, {
"unlock_key": "loschen|2|0",
"unlock_key": "vector|1|0",
"complete": 1
}, {
"unlock_key": "vector|2|0",
"unlock_key": "valhallazero|1|0",
"complete": 1
}, {
"unlock_key": "corpssansorganes|2|0",
"complete": 1
}, {
"unlock_key": "valhallazero|2|0",
"unlock_key": "tiferet|2|0",
"complete": 1
}, {
"unlock_key": "tiferet|1|0",
"complete": 1
}, {
"unlock_key": "ouroboros|2|0",
"unlock_key": "tiemedowngently|2|0",
"complete": 1
}, {
"unlock_key": "tiemedowngently|1|0",
"complete": 1
}, {
"unlock_key": "aegleseeker|2|3|crystalgravity|2",
"complete": 10
}, {
"unlock_key": "tempestissimo|0|101",
"unlock_key": "tempestissimo|2|101",
"complete": 100
}, {
"unlock_key": "syro|2|0",
"complete": 1
"unlock_key": "tempestissimo|1|101",
"complete": 100
}, {
"unlock_key": "ringedgenesis|2|0",
"complete": 1
@@ -1024,11 +1044,14 @@ def arc_all_get(user_id):
}, {
"unlock_key": "snowwhite|2|0",
"complete": 1
}, {
"unlock_key": "senkyou|1|0",
"complete": 1
}, {
"unlock_key": "senkyou|2|0",
"complete": 1
}, {
"unlock_key": "senkyou|1|0",
"unlock_key": "seclusion|1|0",
"complete": 1
}, {
"unlock_key": "scarletlance|2|0",
@@ -1054,6 +1077,12 @@ def arc_all_get(user_id):
}, {
"unlock_key": "reinvent|2|0",
"complete": 1
}, {
"unlock_key": "felis|1|0",
"complete": 1
}, {
"unlock_key": "rekkaresonance|2|0",
"complete": 1
}, {
"unlock_key": "reinvent|1|0",
"complete": 1
@@ -1101,7 +1130,7 @@ def arc_all_get(user_id):
"complete": 1
}, {
"unlock_key": "saikyostronger|2|3|einherjar|2",
"complete": 3
"complete": 6
}, {
"unlock_key": "cyanine|2|0",
"complete": 1
@@ -1112,7 +1141,10 @@ def arc_all_get(user_id):
"unlock_key": "purgatorium|1|0",
"complete": 1
}, {
"unlock_key": "pragmatism|2|0",
"unlock_key": "tiemedowngently|1|0",
"complete": 1
}, {
"unlock_key": "ouroboros|2|0",
"complete": 1
}, {
"unlock_key": "ringedgenesis|1|0",
@@ -1162,6 +1194,12 @@ def arc_all_get(user_id):
}, {
"unlock_key": "melodyoflove|1|0",
"complete": 1
}, {
"unlock_key": "mazymetroplex|2|0",
"complete": 1
}, {
"unlock_key": "seclusion|2|0",
"complete": 1
}, {
"unlock_key": "lucifer|2|0",
"complete": 1
@@ -1177,9 +1215,6 @@ def arc_all_get(user_id):
}, {
"unlock_key": "lostdesire|2|0",
"complete": 1
}, {
"unlock_key": "tiemedowngently|2|0",
"complete": 1
}, {
"unlock_key": "solitarydream|1|0",
"complete": 1
@@ -1192,12 +1227,30 @@ def arc_all_get(user_id):
}, {
"unlock_key": "loschen|1|0",
"complete": 1
}, {
"unlock_key": "syro|2|0",
"complete": 1
}, {
"unlock_key": "aegleseeker|2|3|paperwitch|2",
"complete": 10
}, {
"unlock_key": "livefastdieyoung|1|0",
"complete": 1
}, {
"unlock_key": "shadesoflight|1|0",
"complete": 1
}, {
"unlock_key": "kanagawa|2|0",
"complete": 1
}, {
"unlock_key": "ifi|2|0",
"complete": 1
}, {
"unlock_key": "kanagawa|1|0",
"complete": 1
}, {
"unlock_key": "jump|1|0",
"complete": 1
}, {
"unlock_key": "grievouslady|1|101",
"complete": 100
@@ -1214,28 +1267,7 @@ def arc_all_get(user_id):
"unlock_key": "ignotus|2|0",
"complete": 1
}, {
"unlock_key": "snowwhite|1|0",
"complete": 1
}, {
"unlock_key": "partyvinyl|1|0",
"complete": 1
}, {
"unlock_key": "viciousheroism|1|0",
"complete": 1
}, {
"unlock_key": "gloryroad|0|0",
"complete": 1
}, {
"unlock_key": "axiumcrisis|1|0",
"complete": 1
}, {
"unlock_key": "kanagawa|1|0",
"complete": 1
}, {
"unlock_key": "ifi|2|0",
"complete": 1
}, {
"unlock_key": "jump|2|0",
"unlock_key": "ignotus|1|0",
"complete": 1
}, {
"unlock_key": "nhelv|1|0",
@@ -1246,9 +1278,6 @@ def arc_all_get(user_id):
}, {
"unlock_key": "guardina|2|0",
"complete": 1
}, {
"unlock_key": "guardina|1|0",
"complete": 1
}, {
"unlock_key": "lethaeus|1|0",
"complete": 1
@@ -1258,9 +1287,6 @@ def arc_all_get(user_id):
}, {
"unlock_key": "guardina|0|0",
"complete": 1
}, {
"unlock_key": "jump|1|0",
"complete": 1
}, {
"unlock_key": "oshamascramble|2|0",
"complete": 1
@@ -1276,9 +1302,6 @@ def arc_all_get(user_id):
}, {
"unlock_key": "darakunosono|1|0",
"complete": 1
}, {
"unlock_key": "valhallazero|1|0",
"complete": 1
}, {
"unlock_key": "grimheart|1|0",
"complete": 1
@@ -1288,27 +1311,33 @@ def arc_all_get(user_id):
}, {
"unlock_key": "gothiveofra|1|0",
"complete": 1
}, {
"unlock_key": "cyanine|1|0",
"complete": 1
}, {
"unlock_key": "tempestissimo|3|101",
"complete": 100
}, {
"unlock_key": "overwhelm|2|0",
"complete": 1
}, {
"unlock_key": "chronostasis|2|0",
"complete": 1
}, {
"unlock_key": "gloryroad|2|0",
"complete": 1
}, {
"unlock_key": "etherstrike|1|0",
"complete": 1
}, {
"unlock_key": "singularity|2|0",
"complete": 1
}, {
"unlock_key": "viciousheroism|1|0",
"complete": 1
}, {
"unlock_key": "axiumcrisis|1|0",
"complete": 1
}, {
"unlock_key": "gloryroad|0|0",
"complete": 1
}, {
"unlock_key": "guardina|1|0",
"complete": 1
}, {
"unlock_key": "pragmatism|2|0",
"complete": 1
}, {
"unlock_key": "oracle|2|0",
"complete": 1
}, {
"unlock_key": "genocider|2|0",
"complete": 1
}, {
"unlock_key": "buchigireberserker|2|3|gothiveofra|2",
"complete": 1
@@ -1339,9 +1368,6 @@ def arc_all_get(user_id):
}, {
"unlock_key": "flyburg|2|0",
"complete": 1
}, {
"unlock_key": "oracle|2|0",
"complete": 1
}, {
"unlock_key": "clotho|2|0",
"complete": 1
@@ -1375,12 +1401,39 @@ def arc_all_get(user_id):
}, {
"unlock_key": "espebranch|2|0",
"complete": 1
}, {
"unlock_key": "syro|1|0",
"complete": 1
}, {
"unlock_key": "anokumene|2|0",
"complete": 1
}, {
"unlock_key": "equilibrium_challenge|2|102",
"complete": 1
}, {
"unlock_key": "overwhelm|2|0",
"complete": 1
}, {
"unlock_key": "chronostasis|2|0",
"complete": 1
}, {
"unlock_key": "gloryroad|2|0",
"complete": 1
}, {
"unlock_key": "equilibrium_challenge|1|102",
"complete": 1
}, {
"unlock_key": "aterlbus|2|0",
"complete": 1
}, {
"unlock_key": "dreaminattraction|2|0",
"complete": 1
}, {
"unlock_key": "dreaminattraction|1|0",
"complete": 1
}, {
"unlock_key": "divinelight|2|0",
"complete": 1
}, {
"unlock_key": "goodtek|2|0",
"complete": 1
@@ -1399,24 +1452,27 @@ def arc_all_get(user_id):
}, {
"unlock_key": "dandelion|1|0",
"complete": 1
}, {
"unlock_key": "aegleseeker_challenge|0|102",
"complete": 1
}, {
"unlock_key": "oblivia|1|0",
"complete": 1
}, {
"unlock_key": "cyberneciacatharsis|1|0",
"complete": 1
}, {
"unlock_key": "blrink|1|0",
"complete": 1
}, {
"unlock_key": "livefastdieyoung|2|0",
"complete": 1
}, {
"unlock_key": "corpssansorganes|0|0",
"complete": 1
}, {
"unlock_key": "vector|1|0",
"complete": 1
}, {
"unlock_key": "conflict|2|0",
"complete": 1
}, {
"unlock_key": "ignotus|1|0",
"complete": 1
}, {
"unlock_key": "monochromeprincess|1|0",
"complete": 1
@@ -1468,15 +1524,27 @@ def arc_all_get(user_id):
}, {
"unlock_key": "blaster|1|0",
"complete": 1
}, {
"unlock_key": "genocider|1|0",
"complete": 1
}, {
"unlock_key": "rise|1|0",
"complete": 1
}, {
"unlock_key": "tempestissimo|0|101",
"complete": 100
}, {
"unlock_key": "aegleseeker|2|3|crystalgravity|2",
"complete": 10
}, {
"unlock_key": "tempestissimo|3|101",
"complete": 100
}, {
"unlock_key": "cyanine|1|0",
"complete": 1
}, {
"unlock_key": "axiumcrisis|2|0",
"complete": 1
}, {
"unlock_key": "tempestissimo|2|101",
"complete": 100
}, {
"unlock_key": "solitarydream|2|0",
"complete": 1
@@ -1493,16 +1561,34 @@ def arc_all_get(user_id):
"unlock_key": "linearaccelerator|1|0",
"complete": 1
}, {
"unlock_key": "tempestissimo|1|101",
"complete": 100
"unlock_key": "valhallazero|2|0",
"complete": 1
}, {
"unlock_key": "corpssansorganes|2|0",
"complete": 1
}, {
"unlock_key": "conflict|1|0",
"complete": 1
}, {
"unlock_key": "mazymetroplex|1|0",
"complete": 1
}, {
"unlock_key": "viyellastears|2|0",
"complete": 1
}, {
"unlock_key": "equilibrium_challenge|0|102",
"complete": 1
}, {
"unlock_key": "grievouslady|0|101",
"complete": 100
}, {
"unlock_key": "dreaminattraction|1|0",
"unlock_key": "snowwhite|1|0",
"complete": 1
}, {
"unlock_key": "partyvinyl|1|0",
"complete": 1
}, {
"unlock_key": "jump|2|0",
"complete": 1
}, {
"unlock_key": "saikyostronger|2|3|izana|2",
@@ -1513,33 +1599,27 @@ def arc_all_get(user_id):
}, {
"unlock_key": "halcyon|1|0",
"complete": 1
}, {
"unlock_key": "felis|1|0",
"complete": 1
}, {
"unlock_key": "overwhelm|1|0",
"complete": 1
}, {
"unlock_key": "toaliceliddell|2|0",
"complete": 1
}, {
"unlock_key": "blrink|1|0",
"complete": 1
}, {
"unlock_key": "heavensdoor|2|0",
"complete": 1
}, {
"unlock_key": "genesis|2|0",
"complete": 1
}, {
"unlock_key": "vector|2|0",
"complete": 1
}, {
"unlock_key": "loschen|2|0",
"complete": 1
}, {
"unlock_key": "divinelight|1|0",
"complete": 1
}, {
"unlock_key": "viyellastears|1|0",
"complete": 1
}, {
"unlock_key": "aegleseeker|2|103",
"complete": 1
}, {
"unlock_key": "tiferet|2|0",
"complete": 1
}, {
"unlock_key": "grimheart|2|0",
"complete": 1
@@ -1555,42 +1635,34 @@ def arc_all_get(user_id):
}, {
"unlock_key": "sheriruth|2|0",
"complete": 1
}, {
"unlock_key": "aegleseeker|2|3|paperwitch|2",
"complete": 10
}, {
"unlock_key": "sheriruth|1|0",
"complete": 1
}, {
"unlock_key": "aegleseeker|2|3|loschen|2",
"complete": 10
}, {
"unlock_key": "cyberneciacatharsis|2|0",
"complete": 1
}, {
"unlock_key": "essenceoftwilight|2|0",
"complete": 1
}, {
"unlock_key": "syro|1|0",
"complete": 1
}, {
"unlock_key": "anokumene|2|0",
"complete": 1
}, {
"unlock_key": "freefall|1|0",
"complete": 1
}, {
"unlock_key": "darakunosono|2|0",
"complete": 1
}, {
"unlock_key": "freefall|1|0",
"complete": 1
}, {
"unlock_key": "toaliceliddell|2|0",
"complete": 1
}, {
"unlock_key": "overwhelm|1|0",
"complete": 1
}, {
"unlock_key": "nirvluce|2|0",
"complete": 1
},
{
"unlock_key": "aegleseeker_challenge|0|102",
}, {
"unlock_key": "cyberneciacatharsis|2|0",
"complete": 1
}
]
}]
return {
"user_id": user_id,

View File

@@ -9,6 +9,10 @@ import os
import time
ETO_UNCAP_BONUS_PROGRESS = 7
LUNA_UNCAP_BONUS_PROGRESS = 7
def int2b(x):
# int与布尔值转换
if x is None or x == 0:
@@ -90,8 +94,8 @@ def get_current_map(user_id):
def get_world_all(user_id):
# 读取所有地图信息并处理,返回字典列表
re = []
worlds = get_world_name()
with Connect() as c:
worlds = get_world_name()
for map_id in worlds:
info = get_world_info(map_id)
steps = info['steps']
@@ -121,6 +125,23 @@ def get_world_all(user_id):
return re
def get_available_maps():
# 获取当前可用图(用户设定的),返回字典列表
re = []
for i in Config.AVAILABLE_MAP:
info = get_world_info(i)
del info['steps']
try:
del info['is_locked']
del info['curr_position']
del info['curr_capture']
except:
pass
re.append(info)
return re
def get_user_world(user_id, map_id):
# 获取用户图信息,返回字典
re = {}
@@ -346,12 +367,23 @@ def world_update(c, user_id, song_id, difficulty, rating, clear_type, beyond_gau
'a': user_id, 'b': song_id, 'c': difficulty})
c.execute(
'''select character_id, max_stamina_ts, stamina from user where user_id=?''', (user_id,))
'''select character_id, max_stamina_ts, stamina, is_skill_sealed, is_char_uncapped, is_char_uncapped_override from user where user_id=?''', (user_id,))
x = c.fetchone()
character_id = x[0] if x and x[0] is not None else 0
max_stamina_ts = x[1] if x and x[1] is not None else 0
stamina = x[2] if x and x[2] is not None else 12
c.execute('''select frag1,prog1,overdrive1,frag20,prog20,overdrive20,frag30,prog30,overdrive30 from character where character_id=?''', (character_id,))
is_skill_sealed = x[3] if x and x[3] is not None else 1
skill = False
skill_uncap = False
if not is_skill_sealed:
if x:
skill = True
if x[4] is not None and x[4] == 1:
skill_uncap = True
if x[5] is not None and x[5] == 1:
skill_uncap = False
c.execute('''select frag1,prog1,overdrive1,frag20,prog20,overdrive20,frag30,prog30,overdrive30,skill_id,skill_id_uncap from character where character_id=?''', (character_id,))
x = c.fetchone()
if Config.CHARACTER_FULL_UNLOCK:
@@ -372,10 +404,20 @@ def world_update(c, user_id, song_id, difficulty, rating, clear_type, beyond_gau
flag = server.character.calc_char_value(level, x[0], x[3], x[6])
prog = server.character.calc_char_value(level, x[1], x[4], x[7])
overdrive = server.character.calc_char_value(level, x[2], x[5], x[8])
if x[9] is not None and x[9] != '' and skill:
skill = x[9]
else:
skill = None
if x[10] is not None and x[9] != '' and skill_uncap:
skill_uncap = x[10]
else:
skill_uncap = None
else:
flag = 0
prog = 0
overdrive = 0
skill = None
skill_uncap = None
c.execute('''select current_map from user where user_id = :a''', {
'a': user_id})
@@ -407,6 +449,37 @@ def world_update(c, user_id, song_id, difficulty, rating, clear_type, beyond_gau
rewards, steps, curr_position, curr_capture, info = climb_step(
user_id, map_id, step, y[3], y[2])
# Eto和Luna的技能
character_bonus_progress = None
skill_special = ''
if skill_uncap is not None and skill_uncap and skill_uncap in ['eto_uncap', 'luna_uncap']:
skill_special = skill_uncap
elif skill is not None and skill and skill in ['eto_uncap', 'luna_uncap']:
skill_special = skill
if skill_special == 'eto_uncap':
# eto觉醒技能获得残片奖励时世界模式进度加7
fragment_flag = False
for i in rewards:
for j in i['items']:
if j['type'] == 'fragment':
fragment_flag = True
break
if fragment_flag:
break
if fragment_flag:
character_bonus_progress = ETO_UNCAP_BONUS_PROGRESS
step += character_bonus_progress * step_times
rewards, steps, curr_position, curr_capture, info = climb_step(
user_id, map_id, step, y[3], y[2]) # 二次爬梯,重新计算
elif skill_special == 'luna_uncap':
# luna觉醒技能限制格开始时世界模式进度加7
if 'restrict_id' in steps[0] and 'restrict_type' in steps[0] and steps[0]['restrict_type'] != '' and steps[0]['restrict_id'] != '':
character_bonus_progress = LUNA_UNCAP_BONUS_PROGRESS
step += character_bonus_progress * step_times
rewards, steps, curr_position, curr_capture, info = climb_step(
user_id, map_id, step, y[3], y[2]) # 二次爬梯,重新计算
for i in rewards: # 物品分发
for j in i['items']:
amount = j['amount'] if 'amount' in j else 1
@@ -482,6 +555,9 @@ def world_update(c, user_id, song_id, difficulty, rating, clear_type, beyond_gau
"max_stamina_ts": max_stamina_ts
}
if character_bonus_progress is not None:
re['character_bonus_progress'] = character_bonus_progress
if stamina_multiply != 1:
re['stamina_multiply'] = stamina_multiply
if fragment_multiply != 100:

View File

@@ -165,7 +165,7 @@ def get_user_me(c, user_id):
stamina = x[33]
r = {"is_aprilfools": Config.IS_APRILFOOLS,
"curr_available_maps": [],
"curr_available_maps": server.arcworld.get_available_maps(),
"character_stats": user_character,
"friends": get_user_friend(c, user_id),
"settings": {

View File

@@ -30,10 +30,11 @@ class Connect():
return True
class Sql():
@staticmethod
def select(c, table_name, target_column=[], limit=-1, offset=0, query={}, sort=[]):
def select(c, table_name, target_column=[], query=None):
# 执行查询单句sql语句返回fetchall数据
# 使用准确查询,且在单表内
@@ -51,9 +52,10 @@ class Sql():
where_field = []
where_value = []
for i in query:
where_field.append(i)
where_value.append(query[i])
if query:
for i in query.query:
where_field.append(i)
where_value.append(query.query[i])
if where_field and where_value:
sql += ' where '
@@ -64,16 +66,17 @@ class Sql():
sql_dict[where_field[i]] = where_value[i]
sql += ' and ' + where_field[i] + '=:' + where_field[i]
if sort:
sql += ' order by ' + sort[0]['column'] + ' ' + sort[0]['order']
if len(sort) >= 2:
for i in range(1, len(sort)):
sql += ', ' + sort[i]['column'] + ' ' + sort[i]['order']
if query and query.sort:
sql += ' order by ' + \
query.sort[0]['column'] + ' ' + query.sort[0]['order']
for i in range(1, len(query.sort)):
sql += ', ' + query.sort[i]['column'] + \
' ' + query.sort[i]['order']
if limit >= 0:
if query and query.limit >= 0:
sql += ' limit :limit offset :offset'
sql_dict['limit'] = limit
sql_dict['offset'] = offset
sql_dict['limit'] = query.limit
sql_dict['offset'] = query.offset
c.execute(sql, sql_dict)

View File

@@ -8,7 +8,7 @@ class Config():
主机的地址和端口号
Host and port of your server
'''
HOST = '192.168.1.101'
HOST = '0.0.0.0'
PORT = '80'
'''
--------------------
@@ -19,7 +19,7 @@ class Config():
游戏API地址前缀
Game API's URL prefix
'''
GAME_API_PREFIX = '/kusoatui/15'
GAME_API_PREFIX = '/earlgrey/16'
'''
--------------------
'''
@@ -30,7 +30,8 @@ class Config():
Allowed game versions
If it is blank, all are allowed.
'''
ALLOW_APPVERSION = ['3.5.3', '3.5.3c', '3.6.4', '3.6.4c']
ALLOW_APPVERSION = ['3.5.3', '3.5.3c',
'3.9.0', '3.9.0c', '3.9.1', '3.9.1c']
'''
--------------------
'''
@@ -68,6 +69,16 @@ class Config():
--------------------
'''
'''
--------------------
世界模式当前活动图设置
Current available maps in world mode
'''
AVAILABLE_MAP = [] # Ex. ['test', 'test2']
'''
--------------------
'''
'''
--------------------
Web后台管理页面的用户名和密码
@@ -96,7 +107,7 @@ class Config():
API interface full control permission Token
If you don't want to use it, leave it blank.
'''
API_TOKEN = '123'
API_TOKEN = ''
'''
--------------------
'''
@@ -169,6 +180,18 @@ class Config():
--------------------
'''
'''
--------------------
数据库更新时,是否采用最新的角色数据,如果你想采用最新的官方角色数据
注意:如果是,旧的数据将丢失;如果否,某些角色的数据变动将无法同步
If using the latest character data when updating database. If you want to only keep newest official character data, please set it `True`.
Note: If `True`, the old data will be lost; If `False`, the data changes of some characters will not be synchronized.
'''
UPDATE_WITH_NEW_CHARACTER_DATA = True
'''
--------------------
'''
'''
--------------------
是否全解锁搭档

View File

@@ -37,6 +37,10 @@
<span class="char-num">{{x['type']}}</span>
<br />
<span>Amount: </span>
<span class="char-num">{{x['amount']}}</span>
<br />
{% if not loop.last %}

View File

@@ -17,8 +17,11 @@
<option value='pack'>Song pack</option>
<option value='world_song'>World song</option>
<option value='character'>Character</option>
<option value='core'>Core</option>
</select>
</div>
<label for="amount">Amount</label>
<input name="amount" id="amount" value="1" required>
<br />
<input type="submit" value="Add">
</form>
@@ -36,6 +39,7 @@
<option value='pack'>Pack</option>
<option value='world_song'>World song</option>
<option value='character'>Character</option>
<option value='core'>Core</option>
</select>
</div>
<br />

View File

@@ -418,7 +418,7 @@ def all_character():
def change_character():
# 修改角色数据
skill_ids = ['No_skill', 'gauge_easy', 'note_mirror', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami']
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily', 'skill_kanae_midsummer', 'eto_uncap', 'luna_uncap']
return render_template('web/changechar.html', skill_ids=skill_ids)
@@ -777,12 +777,12 @@ def change_purchase():
discount_from = int(time.mktime(time.strptime(
discount_from, "%Y-%m-%dT%H:%M"))) * 1000
else:
discount_from = None
discount_from = -1
if discount_to:
discount_to = int(time.mktime(time.strptime(
discount_to, "%Y-%m-%dT%H:%M"))) * 1000
else:
discount_to = None
discount_to = -1
except:
error = '数据错误 Wrong data.'
flash(error)
@@ -847,6 +847,7 @@ def change_purchase_item():
purchase_name = request.form['purchase_name']
item_id = request.form['item_id']
item_type = request.form['type']
amount = int(request.form['amount'])
except:
error = '数据错误 Wrong data.'
flash(error)
@@ -862,8 +863,8 @@ def change_purchase_item():
c.execute(
'''select exists(select * from item where item_id=? and type=?)''', (item_id, item_type))
if c.fetchone() == (1,):
c.execute('''insert into purchase_item values(?,?,?)''',
(purchase_name, item_id, item_type))
c.execute('''insert into purchase_item values(?,?,?,?)''',
(purchase_name, item_id, item_type, amount))
flash('''购买项目的物品添加成功 Successfully add the purchase's item.''')
else:
error = '''物品不存在 The item does not exist.'''

View File

@@ -5,6 +5,7 @@ import json
import server.arcscore
import hashlib
from random import Random
from setting import Config
def int2b(x):
@@ -204,13 +205,13 @@ def update_database():
update_one_table(c1, c2, 'user_role')
update_one_table(c1, c2, 'power')
update_one_table(c1, c2, 'role_power')
update_one_table(c1, c2, 'api_auth')
update_one_table(c1, c2, 'api_login')
update_one_table(c1, c2, 'user_char')
# ---You can comment this line by yourself, if you want to only keep newest official character data.
update_one_table(c1, c2, 'character')
# ---
if not Config.UPDATE_WITH_NEW_CHARACTER_DATA:
update_one_table(c1, c2, 'character')
update_user_char(c2) # 更新user_char_full
os.remove('database/old_arcaea_database.db')
@@ -301,7 +302,7 @@ def get_all_purchase():
items = []
if y:
for j in y:
items.append({'item_id': j[1], 'type': j[2]})
items.append({'item_id': j[1], 'type': j[2], 'amount':j[3]})
re.append({'purchase_name': i[0],
'price': i[1],