Difficult-Rocket/Difficult_Rocket/api/calculation.py
2022-01-19 20:21:57 +08:00

309 lines
7.5 KiB
Python

# -------------------------------
# Difficult Rocket
# Copyright © 2021-2022 by shenjackyuanjie
# All rights reserved
# -------------------------------
"""
writen by shenjackyuanjie
mail: 3695888@qq.com
github: @shenjackyuanjie
gitee: @shenjackyuanjie
"""
import math
import decimal
from typing import List, Optional, Union
from decimal import Decimal
# linear_algebra
def C_R_P(position: List, degrees: List): # stand for calculation
"""
very thanks for lenny from pyglet developer
https://github.com/LennyPhoenix
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
"""
Physics calculation
"""
def is_decimal(A: any) -> bool:
if isinstance(A, decimal.Decimal):
return False
else:
return True
def F_D(A: decimal, B: decimal) -> decimal:
if is_decimal(A) and is_decimal(B):
return A / B
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
def D_C(listA: list, listB: list): # stand for Duplicate check
"""
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
"""
for unit in listB:
if unit in listA:
listA.remove(unit)
listB.remove(unit)
else:
continue
listA.sort()
listB.sort()
def S_C_float_check(SC): # stand for Scientific notation's float check
"""
formats:
SC list format:docs.basic_config.json:basic_number"""
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
"""
formats:
A & B & C list format:docs.basic_config.json:basic_number"""
if len(SN) < 2:
raise TypeError('it need more than 1!')
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):
"""
formats:
A & B list format:docs.basic_config.json:basic_number"""
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]
if Unit1 is None:
Unit1 = []
D_C(Unit1, Unit2)
R += [Unit1, Unit2]
return R
def S_N_D(A, B): # stand for Scientific notation divided
"""
formats:
A & B list format:docs.basic_config:basic_number"""
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]
if Unit1 is None:
Unit1 = []
D_C(Unit1, Unit2)
R += [Unit1, Unit2]
return R
def G_C(M, m, R, G): # stand for gravity calculation
"""
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
"""
g = basic_force()
A = S_N_M(M, m, G)
g = S_N_D(A, S_N_M(R, R))
return g
def distance(A, B):
"""
formats:
A & B format: docs.basic_config:basic_poi
"""
poi_dis = basic_poi()
for x in A, B:
x = decimal.Decimal(str(x))
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]
def _BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None) -> list:
if unit1 is None:
unit1 = []
if unit2 is None:
unit2 = []
if is_decimal(float_num): # is decimal class?
return [int_num, float_num, unit1, unit2] # is just return
else:
return [int_num, decimal.Decimal(str(float_num)), unit1, unit2] # no create a decimal class
def BasicNumber(int_num=0, float_num=1, unit1=None, unit2=None, num=1) -> list:
numbers = []
if num > 1:
for x in range(0, num, 1):
numbers.append(_BasicNumber(int_num, float_num, unit1, unit2))
elif num == 1:
return _BasicNumber(int_num, float_num, unit1, unit2)
else: # num < 1
raise TypeError('you should give me a num with >= 1!')
return numbers
class BasicNumberClass:
def __init__(self, int_num=0, float_num=1, unit1=None, unit2=None):
self.int = int_num
self.float = decimal.Decimal(str(float_num))
if unit1:
self.units1 = unit1
else:
self.units1 = []
if unit2:
self.units2 = unit2
else:
self.units2 = []
def sort(self):
self.units1.sort()
self.units2.sort()
def float_int_check(self, int_=None, float_=None):
if not int_:
int_ = 1
if not float_:
float_ = decimal.Decimal(1.0)
while float_ > 10:
float_ / 10
int_ + 1
else:
while float_ < 0.1:
float_ * 10
int_ - 1
return [int_, float_]
def units(self) -> list or bool:
if (self.units1 == []) and (self.units2 == []):
return None
data = self.units1
data.append(self.units2)
return data
def __str__(self):
return [self.float, self.int, self.units1, self.units2]
def __add__(self, other):
o_type = type(other)
if o_type == type(self):
self.sort()
other.sort()
if self.units() == other.units():
self_num = self.float * (10 ** self.int)
other_num = other.float * (10 ** other.float)
r_float = self_num + other_num
check = self.float_int_check(1, r_float)
self.float = check[0]
self.int = check[1]
elif o_type == type(decimal.Decimal('1.0')) and not self.units():
pass
def __radd__(self, other):
self.__add__(self)
def __mul__(self, other):
pass
def __rmul__(self, other):
self.__mul__(self)
def __truediv__(self, other):
pass
def basic_poi(poi_type=None) -> list:
if poi_type is None:
return BasicNumber(unit1='m', num=2)
if poi_type == 'chunk':
return [BasicNumber(unit1='chunk', num=2), BasicNumber(unit1='m', num=2)]
def basic_force() -> list:
return BasicNumber(unit1='N', num=2)
class ScientificNumber:
"""
A class of Scientific notation
give float and integer and unit
"""
def __init__(self,
小数: Union[float, Decimal] = 1.0,
指数: int = 0,
乘单位: list = list,
除单位: list = list):
if not isinstance(小数, Decimal):
self.小数 = Decimal(小数)
else:
self.小数 = 小数
self.指数 = 指数
self.乘单位 = 乘单位
self.除单位 = 除单位
self.check()
def check(self):
while self.小数 > 10:
self.小数 /= 10
self.指数 += 1
while self.小数 < 1:
self.小数 *= 10
self.指数 -= 1
self.除单位.sort()
self.乘单位.sort()