2021-09-08 23:38:34 +08:00
|
|
|
|
# -------------------------------
|
|
|
|
|
# Difficult Rocket
|
|
|
|
|
# Copyright © 2021 by shenjackyuanjie
|
|
|
|
|
# All rights reserved
|
|
|
|
|
# -------------------------------
|
|
|
|
|
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2020-12-16 06:33:33 +08:00
|
|
|
|
writen by shenjackyuanjie
|
2021-09-08 23:38:34 +08:00
|
|
|
|
mail: 3695888@qq.com
|
2021-07-08 20:42:22 +08:00
|
|
|
|
github: @shenjackyuanjie
|
2021-09-08 23:38:34 +08:00
|
|
|
|
gitee: @shenjackyuanjie
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2020-12-16 06:33:33 +08:00
|
|
|
|
|
2021-08-13 12:25:29 +08:00
|
|
|
|
import os
|
2021-08-24 22:31:52 +08:00
|
|
|
|
import sys
|
|
|
|
|
import time
|
2021-09-22 06:21:48 +08:00
|
|
|
|
import math
|
|
|
|
|
import decimal
|
|
|
|
|
import logging
|
2021-08-24 22:31:52 +08:00
|
|
|
|
import traceback
|
2021-09-22 06:21:48 +08:00
|
|
|
|
import configparser
|
2021-09-05 00:50:05 +08:00
|
|
|
|
|
2021-09-24 00:04:56 +08:00
|
|
|
|
from typing import List
|
|
|
|
|
from xml.dom.minidom import parse
|
2021-04-03 12:15:24 +08:00
|
|
|
|
|
2021-08-24 22:31:52 +08:00
|
|
|
|
if __name__ == '__main__': # been start will not run this
|
|
|
|
|
sys.path.append('/bin/libs')
|
|
|
|
|
sys.path.append('/bin')
|
|
|
|
|
|
2021-09-22 06:21:48 +08:00
|
|
|
|
from libs import json5
|
2021-07-08 20:42:22 +08:00
|
|
|
|
|
2021-02-06 16:41:54 +08:00
|
|
|
|
# logger
|
2021-05-24 05:58:16 +08:00
|
|
|
|
tools_logger = logging.getLogger('part-tools')
|
2021-07-08 20:42:22 +08:00
|
|
|
|
"""
|
|
|
|
|
file configs
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def report_file_error(filetype: str, error_type, filename: str, stack: any):
|
2021-08-13 12:25:29 +08:00
|
|
|
|
error = traceback.format_exc()
|
|
|
|
|
if isinstance(error_type, FileNotFoundError):
|
2021-09-05 00:50:05 +08:00
|
|
|
|
log = 'no {} file was found!: \n file name: {} \n file type: {} \n stack: {} \n traceback: {}'.format(filetype, filename, filetype, stack,
|
|
|
|
|
error)
|
2021-08-13 12:25:29 +08:00
|
|
|
|
elif isinstance(error_type, KeyError):
|
2021-07-08 20:42:22 +08:00
|
|
|
|
log = 'no stack in %s file: %s \n file type: %s \n stack: %s' % (filetype, filename, filetype, stack)
|
|
|
|
|
else:
|
|
|
|
|
log = 'some error has been found! \n error type: %s \n file name: %s \n file type: %s \n stack: %s' % (error_type, filename, filetype, stack)
|
|
|
|
|
tools_logger.exception(log)
|
|
|
|
|
|
|
|
|
|
|
2021-09-28 22:47:19 +08:00
|
|
|
|
def load_file(file_name: str, stack=None) -> dict:
|
2021-07-08 20:42:22 +08:00
|
|
|
|
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
|
|
|
|
|
try:
|
|
|
|
|
if (f_type == 'json5') or (f_type == 'json'):
|
|
|
|
|
try:
|
|
|
|
|
with open(file_name, 'r', encoding='utf-8') as jf: # jf -> json file
|
|
|
|
|
rd = json5.load(jf)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
with open(file_name, 'r', encoding='gbk') as jf:
|
|
|
|
|
rd = json5.load(jf)
|
|
|
|
|
tools_logger.info('文件 %s 解码错误,已重新使用gbk编码打开' % file_name)
|
|
|
|
|
if stack is not None:
|
|
|
|
|
rd = rd[stack]
|
|
|
|
|
return rd
|
|
|
|
|
elif f_type == 'xml':
|
|
|
|
|
xml_load = parse(file_name)
|
|
|
|
|
if stack is not None:
|
|
|
|
|
xml_get = xml_load.getElementsByTagName(stack)
|
|
|
|
|
return xml_get
|
|
|
|
|
else:
|
|
|
|
|
return xml_load
|
2021-08-24 22:31:52 +08:00
|
|
|
|
elif (f_type == 'config') or (f_type == 'conf') or (f_type == 'ini'):
|
2021-07-08 20:42:22 +08:00
|
|
|
|
cp = configparser.ConfigParser() # cp -> config parser
|
|
|
|
|
cp.read(file_name) # config parser -> reader
|
|
|
|
|
rd = {}
|
|
|
|
|
for section in cp.sections():
|
|
|
|
|
rd[section] = {}
|
|
|
|
|
for data in cp[section]:
|
|
|
|
|
rd[section][data] = cp[section][data]
|
|
|
|
|
if stack:
|
|
|
|
|
rd = rd[stack]
|
|
|
|
|
return rd
|
2021-08-13 12:25:29 +08:00
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
log = 'no {} file was found!: \n file name: {} \n file type: {} \n stack: {}'.format(f_type, file_name, f_type, stack)
|
|
|
|
|
tools_logger.error(log)
|
|
|
|
|
raise
|
|
|
|
|
except KeyError:
|
|
|
|
|
log = 'no stack in {} file {} was found! \n file type: {} \n file name: {} \n stack: {}'.format(f_type, file_name, f_type, file_name, stack)
|
|
|
|
|
tools_logger.error(log)
|
|
|
|
|
raise
|
2021-07-08 20:42:22 +08:00
|
|
|
|
except Exception as exp:
|
2021-08-13 12:25:29 +08:00
|
|
|
|
log = 'some error has been found!\n error type: {} \n file name: {} \n file type: {} \n stack: {}'.format(type(exp), file_name, f_type, stack)
|
|
|
|
|
tools_logger.error(log)
|
|
|
|
|
raise
|
2021-07-08 20:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# main config
|
2021-09-28 22:47:19 +08:00
|
|
|
|
main_config_file = load_file('./configs/main.config')
|
2021-07-08 20:42:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_At(name, in_xml, need_type=str):
|
|
|
|
|
"""
|
|
|
|
|
get Attribute from a XML tree
|
|
|
|
|
will raise TypeError if input is not str or list
|
|
|
|
|
XML no! Json5 yes!
|
|
|
|
|
"""
|
|
|
|
|
name_type = type(name)
|
|
|
|
|
if name_type == list:
|
|
|
|
|
At_list = []
|
|
|
|
|
for need_name in name:
|
|
|
|
|
if in_xml.hasAttribute(need_name):
|
|
|
|
|
get = in_xml.getAttribute(need_name)
|
|
|
|
|
At_list.append(need_type(get))
|
|
|
|
|
else:
|
|
|
|
|
continue
|
|
|
|
|
return At_list
|
|
|
|
|
elif name_type == str:
|
|
|
|
|
if in_xml.hasAttribute(name):
|
|
|
|
|
At = in_xml.getAttribute(name)
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
else:
|
|
|
|
|
raise TypeError('only str and list type is ok but you give me a' + name_type + 'type')
|
|
|
|
|
return need_type(At)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def default_name_handler(name_: str) -> str:
|
|
|
|
|
"""
|
|
|
|
|
won't change the string
|
|
|
|
|
just return one
|
|
|
|
|
"""
|
|
|
|
|
name = name_
|
|
|
|
|
name = name.replace('{time.time}', str(time.time()))
|
|
|
|
|
name = name.replace('{dir}', str(os.getcwd()))
|
|
|
|
|
name = name.replace('{py_v}', str(sys.version.split(' ')[0]))
|
|
|
|
|
name = name.replace('{version}', str(main_config_file['runtime']['version']))
|
2021-08-13 12:25:29 +08:00
|
|
|
|
name = name.replace('{write_v}', str(main_config_file['runtime']['write_py_v']))
|
2021-07-08 20:42:22 +08:00
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
|
2021-08-13 12:25:29 +08:00
|
|
|
|
def name_handler(name: str, formats: dict = None) -> str:
|
2021-07-08 20:42:22 +08:00
|
|
|
|
if formats is None:
|
|
|
|
|
return default_name_handler(name)
|
|
|
|
|
name = default_name_handler(name)
|
|
|
|
|
for need_replace in formats:
|
|
|
|
|
replace = formats[need_replace]
|
|
|
|
|
if need_replace == '{date}':
|
2021-08-13 12:25:29 +08:00
|
|
|
|
if '{date}' in formats:
|
|
|
|
|
replace = time.strftime(formats['{date}'], time.gmtime(time.time()))
|
|
|
|
|
else:
|
|
|
|
|
replace = time.strftime(main_config_file['runtime']['date_fmt'], time.gmtime(time.time()))
|
2021-07-08 20:42:22 +08:00
|
|
|
|
name = name.replace(need_replace, replace)
|
|
|
|
|
return name
|
|
|
|
|
|
|
|
|
|
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
some tools
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2020-12-23 23:19:16 +08:00
|
|
|
|
|
2021-09-02 22:47:10 +08:00
|
|
|
|
yes = ['true', '1', 1, 1.0, True]
|
|
|
|
|
no = ['false', '0', 0, 0.0, False, None]
|
2020-12-16 06:33:33 +08:00
|
|
|
|
|
2021-09-02 22:47:10 +08:00
|
|
|
|
|
|
|
|
|
def format_bool(thing) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
:param thing 啥都行,只要是能传进来的都可以
|
|
|
|
|
|
|
|
|
|
如果看起来像"True" 比如 'true','1',1
|
|
|
|
|
就返回 True
|
|
|
|
|
如果看起来像"False" 比如 'false','0',0
|
|
|
|
|
就返回 False
|
|
|
|
|
都不像就 raise TypeError
|
|
|
|
|
感谢来自MCDReforged的各位同志《你能在MCDR群里聊除了MCDR的任何东西》
|
|
|
|
|
"""
|
|
|
|
|
if (thing in yes) or (isinstance(thing, str) and thing.lower() in yes):
|
2020-12-16 06:33:33 +08:00
|
|
|
|
return True
|
2021-09-02 22:47:10 +08:00
|
|
|
|
elif (thing in no) or (isinstance(thing, str) and thing.lower() in no):
|
2020-12-16 06:33:33 +08:00
|
|
|
|
return False
|
|
|
|
|
else:
|
2021-09-02 22:47:10 +08:00
|
|
|
|
raise TypeError("Need a 'like bool' not a {}".format(thing))
|
2020-12-22 18:13:59 +08:00
|
|
|
|
|
2020-12-23 23:19:16 +08:00
|
|
|
|
|
2021-04-09 19:49:02 +08:00
|
|
|
|
level_ = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
|
2021-04-17 01:14:38 +08:00
|
|
|
|
logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
|
2021-04-09 19:49:02 +08:00
|
|
|
|
|
|
|
|
|
|
2021-02-14 23:15:54 +08:00
|
|
|
|
def log_level(level):
|
|
|
|
|
if level in level_:
|
|
|
|
|
if (level == 'DEBUG') or (level == logging.DEBUG):
|
|
|
|
|
return logging.DEBUG
|
|
|
|
|
if (level == 'INFO') or (level == logging.INFO):
|
|
|
|
|
return logging.INFO
|
|
|
|
|
if (level == 'WARNING') or (level == logging.WARNING):
|
|
|
|
|
return logging.WARNING
|
|
|
|
|
if (level == 'ERROR') or (level == logging.ERROR):
|
|
|
|
|
return logging.ERROR
|
|
|
|
|
if (level == 'CRITICAL') or (level == logging.CRITICAL):
|
|
|
|
|
return logging.CRITICAL
|
|
|
|
|
else:
|
2021-07-08 20:42:22 +08:00
|
|
|
|
raise ValueError('Need a like logging.level thing not anything else')
|
2021-02-14 23:15:54 +08:00
|
|
|
|
|
2021-04-03 12:15:24 +08:00
|
|
|
|
|
2021-03-20 10:52:40 +08:00
|
|
|
|
# linear_algebra
|
2021-02-14 23:15:54 +08:00
|
|
|
|
|
2021-04-03 12:15:24 +08:00
|
|
|
|
def C_R_P(position, degrees): # stand for calculation
|
2021-03-20 10:52:40 +08:00
|
|
|
|
"""
|
2021-07-08 20:42:22 +08:00
|
|
|
|
very thanks for lenny from pyglet developer
|
2021-03-20 10:56:08 +08:00
|
|
|
|
https://github.com/LennyPhoenix
|
2021-03-20 10:52:40 +08:00
|
|
|
|
this part of code is write by him
|
|
|
|
|
"""
|
|
|
|
|
radians = degrees * (math.pi / 180)
|
|
|
|
|
cos = math.cos(radians)
|
|
|
|
|
sin = math.sin(radians)
|
|
|
|
|
rotated_pos = (position[0] * cos - position[1] * sin, position[0] * sin + position[1] * cos)
|
|
|
|
|
return rotated_pos
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
Physics calculation
|
2021-03-20 10:52:40 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
|
|
|
|
|
|
2021-01-25 19:23:16 +08:00
|
|
|
|
def is_decimal(A: any) -> bool:
|
2021-09-24 00:04:56 +08:00
|
|
|
|
if isinstance(A, decimal.Decimal):
|
2021-01-25 17:24:00 +08:00
|
|
|
|
return False
|
2021-01-27 10:32:25 +08:00
|
|
|
|
else:
|
|
|
|
|
return True
|
2021-01-25 17:24:00 +08:00
|
|
|
|
|
|
|
|
|
|
2021-01-25 19:23:16 +08:00
|
|
|
|
def F_D(A: decimal, B: decimal) -> decimal:
|
2021-01-25 17:24:00 +08:00
|
|
|
|
if is_decimal(A) and is_decimal(B):
|
|
|
|
|
return A / B
|
2021-01-25 17:11:16 +08:00
|
|
|
|
|
|
|
|
|
|
2021-01-27 10:32:25 +08:00
|
|
|
|
def F_Mu(A: decimal, B: decimal) -> decimal:
|
|
|
|
|
if is_decimal(A) and is_decimal(B):
|
|
|
|
|
return A * B
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def F_Mi(A: decimal, B: decimal) -> decimal:
|
|
|
|
|
if is_decimal(A) and is_decimal(B):
|
|
|
|
|
return A - B
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def F_A(A: decimal, B: decimal) -> decimal:
|
|
|
|
|
if is_decimal(A) and is_decimal(B):
|
|
|
|
|
return A + B
|
2021-01-25 17:11:16 +08:00
|
|
|
|
|
|
|
|
|
|
2021-07-08 20:42:22 +08:00
|
|
|
|
def D_C(listA: list, listB: list): # stand for Duplicate check
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2020-12-22 18:13:59 +08:00
|
|
|
|
usage:\n
|
|
|
|
|
input two list\n
|
|
|
|
|
the fun will do duplicate check and sort then\n
|
|
|
|
|
the fun won't return any thing just change the list now
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2020-12-22 18:13:59 +08:00
|
|
|
|
for unit in listB:
|
|
|
|
|
if unit in listA:
|
|
|
|
|
listA.remove(unit)
|
|
|
|
|
listB.remove(unit)
|
|
|
|
|
else:
|
|
|
|
|
continue
|
|
|
|
|
listA.sort()
|
|
|
|
|
listB.sort()
|
2020-12-23 23:19:16 +08:00
|
|
|
|
|
2021-01-23 19:55:35 +08:00
|
|
|
|
|
2021-02-14 19:03:36 +08:00
|
|
|
|
def S_C_float_check(SC): # stand for Scientific notation's float check
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
2021-04-02 23:31:54 +08:00
|
|
|
|
SC list format:docs.basic_config.json:basic_number"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
while SC[0] >= 10:
|
|
|
|
|
SC[0] = F_D(SC[0], 10)
|
|
|
|
|
SC[1] += 1
|
|
|
|
|
while SC[0] < 1:
|
|
|
|
|
SC[0] = F_Mu(SC[0], 10)
|
|
|
|
|
SC[1] -= 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def S_N_M(*SN): # stand for Scientific notation multiple
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
2021-04-02 23:31:54 +08:00
|
|
|
|
A & B & C list format:docs.basic_config.json:basic_number"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
if len(SN) < 2:
|
2021-07-08 20:42:22 +08:00
|
|
|
|
raise TypeError('it need more than 1!')
|
2021-01-23 19:55:35 +08:00
|
|
|
|
elif len(SN) == 2:
|
|
|
|
|
return __S_N_M(SN[0], SN[1])
|
|
|
|
|
else:
|
|
|
|
|
R = __S_N_M(SN[0], SN[1])
|
|
|
|
|
for A in SN[2:]:
|
|
|
|
|
R = __S_N_M(R, A)
|
|
|
|
|
return R
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __S_N_M(A, B):
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
2021-04-02 23:31:54 +08:00
|
|
|
|
A & B list format:docs.basic_config.json:basic_number"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
R = [F_Mu(A[0], B[0]), A[1] + B[1]]
|
|
|
|
|
S_C_float_check(R)
|
|
|
|
|
Unit1, Unit2 = A[2] + B[2], A[3] + B[3]
|
2021-01-27 10:32:25 +08:00
|
|
|
|
if Unit1 is None:
|
2021-01-23 19:55:35 +08:00
|
|
|
|
Unit1 = []
|
2021-01-25 17:01:54 +08:00
|
|
|
|
D_C(Unit1, Unit2)
|
2021-01-23 19:55:35 +08:00
|
|
|
|
R += [Unit1, Unit2]
|
|
|
|
|
return R
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def S_N_D(A, B): # stand for Scientific notation divided
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
2021-04-02 23:31:54 +08:00
|
|
|
|
A & B list format:docs.basic_config:basic_number"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
R = [F_D(A[0], B[0]), A[1] - B[1]]
|
|
|
|
|
S_C_float_check(R)
|
|
|
|
|
Unit1, Unit2 = A[2] + B[3], A[3] + B[2]
|
2021-02-03 22:04:34 +08:00
|
|
|
|
if Unit1 is None:
|
2021-01-23 19:55:35 +08:00
|
|
|
|
Unit1 = []
|
2021-01-25 17:01:54 +08:00
|
|
|
|
D_C(Unit1, Unit2)
|
2021-01-23 19:55:35 +08:00
|
|
|
|
R += [Unit1, Unit2]
|
|
|
|
|
return R
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def G_C(M, m, R, G): # stand for gravity calculation
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
|
|
|
|
M : ship's mass
|
|
|
|
|
m : planet's mass
|
|
|
|
|
R : distance to the planet
|
|
|
|
|
G : Gravitational constant
|
|
|
|
|
M & m & R format: docs.basic_config:basic_number
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-02-03 22:04:34 +08:00
|
|
|
|
g = configs.basic_force()
|
2021-01-23 19:55:35 +08:00
|
|
|
|
A = S_N_M(M, m, G)
|
|
|
|
|
g = S_N_D(A, S_N_M(R, R))
|
|
|
|
|
return g
|
|
|
|
|
|
|
|
|
|
|
2021-09-24 00:04:56 +08:00
|
|
|
|
def distance(A, B):
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-01-23 19:55:35 +08:00
|
|
|
|
formats:
|
|
|
|
|
A & B format: docs.basic_config:basic_poi
|
2021-04-02 23:31:54 +08:00
|
|
|
|
"""
|
2021-02-03 22:04:34 +08:00
|
|
|
|
poi_dis = configs.basic_poi()
|
2021-02-07 13:50:19 +08:00
|
|
|
|
for x in A, B:
|
|
|
|
|
x = decimal.Decimal(str(x))
|
2021-02-03 22:04:34 +08:00
|
|
|
|
xd = A[0] - B[0]
|
|
|
|
|
yd = A[1] - B[1]
|
|
|
|
|
poi_dis[0] = xd
|
|
|
|
|
poi_dis[1] = yd
|
|
|
|
|
# 勾股定理
|
|
|
|
|
poi_dis[0] **= 2
|
|
|
|
|
poi_dis[1] **= 2
|
|
|
|
|
poi_dis.append(poi_dis[0] + poi_dis[1])
|
|
|
|
|
poi_dis[2] **= 0.5
|
|
|
|
|
return poi_dis[2]
|