Commit 6552d580 authored by Vladimir Zhukov's avatar Vladimir Zhukov
Browse files

total refactoring

parent 1e09fb33
Pipeline #1476 passed with stage
in 2 seconds
TASKS = {
'task_0': {
'name': 'Кибернетические сборники',
'description': 'Установление новых, более точных оценок функции Шеннона и публикация в ведущих журналах.',
'production_science': 'science_0',
'production_base': 1,
'production_exp': 2,
't1': {
'name': 'T1',
'description': 'T1 description',
'science': 's1',
'prod_base': 1,
'prod_exp': 2,
},
'task_1': {
'name': 'Прикладные идеи Шуплецова',
'description': 'Разработка методов синтеза схем для функций и систем функций, встречающихся в приложении.',
'production_science': 'science_0',
'production_base': 1,
'production_exp': 2,
't2': {
'name': 'T2',
'description': 'T2 description',
'science': 's2',
'prod_base': 1,
'prod_exp': 2,
},
'task_2': {
'name': 'Контрольные по ОКам',
'description': 'Подготовка объёмного количества теоретических вопросов, а также задач по различным темам курса.',
'production_science': 'science_2',
'production_base': 1,
'production_exp': 2,
},
'task_3': {
'name': 'Контактные многополюсники',
'description': 'Пока другие разгадывают сканворды, Сергей Андреевич всё рисует контактные схемы.',
'production_science': 'science_2',
'production_base': 1,
'production_exp': 5,
},
'task_4': {
'name': 'Рефлексивно-рекурсивные схемы',
'description': 'РРСФЭ в базисе Б называется последовательность СФЭ сигма 1, сигма 2 и так далее ... Кошмар какой.',
'production_science': 'science_3',
'production_base': 1,
'production_exp': 3,
't3': {
'name': 'T3',
'description': 'T3 description',
'science': 's3',
'prod_base': 1,
'prod_exp': 2,
},
}
SCIENCE = {
'science_0': {
'name': 'Логический синтез',
'description': 'Новейшие разработки в области логического синтеза. Улучшает производительность ПЛИС для некоторых задач.',
'task_key': 'task_0',
's1': {
'name': 'S1',
'description': 'S1 description',
'resource': 't1',
'cost_base': (1, 0),
'cost_exp': 10,
'cost_exp': 2,
},
'science_1': {
'name': 'Физический синтез',
'description': 'Исследования в области физического синтеза. В рамках данной работы в том числе производятся ПЛИС.',
'task_key': 'task_1',
's2': {
'name': 'S2',
'description': 'S2 description',
'resource': 't1',
'cost_base': (1, 0),
'cost_exp': 10,
'cost_exp': 2,
},
'science_2': {
'name': 'Основы кибернетики',
'description': 'Изложение наиболее значимых кибернетических результатов в поняном студентам виде.',
'task_key': 'task_0',
'cost_base': (100, 0),
'cost_exp': 3,
'sp1': {
'name': 'SP1',
'description': 'SP1 description',
'resource': 't2',
'cost_base': (1, 0),
'cost_exp': 2,
},
'science_3': {
'name': 'Обобщение известных моделей',
'description': 'Когда уже получены все результаты для СФЭ, формул и КС, хочется усложнить модель, например, добавив произвольный базис.',
'task_key': 'task_3',
'cost_base': (1, 2),
'cost_exp': 50
's3': {
'name': 'S3',
'description': 'S3 description',
'resource': 't2',
'cost_base': (1, 0),
'cost_exp': 2,
},
}
PLIS_SCIENCES = [
'sp1',
]
UNIVERSITY = {
'university_0': {
'name': 'Бакалавры',
'description': 'Преподавание 3-му курсу Основ кибернетики, пропаганда культа личности Светила.',
'task_key': 'task_2',
'cost': (10, 1),
'u1': {
'name': 'U1',
'description': 'U1 description',
'previous': None,
'resource': 't3',
'cost': (1, 0),
},
'u2': {
'name': 'U2',
'description': 'U2 description',
'previous': 'u1',
'resource': 't3',
'cost': (1, 0),
},
}
GRANTS = {
'g1': {
'name': 'G1',
'description': 'G1 description',
'resource': 'u1',
'cost_base': (1, 0),
'cost_exp': 2,
},
'g2': {
'name': 'G2',
'description': 'G2 description',
'resource': 'u2',
'cost_base': (1, 0),
'cost_exp': 2,
}
}
import copy
import time
from .config import TASKS, SCIENCE, UNIVERSITY
from .config import (
TASKS,
SCIENCE,
PLIS_SCIENCES,
UNIVERSITY,
GRANTS
)
from .models import GameState
from .utils import convert_to_exp_amount, convert_to_value
......@@ -40,6 +46,25 @@ class JsonWrapper:
else:
self.json['amount'] = value
@property
def plis_used(self):
return self.json.get('plis_used', 0)
@plis_used.setter
def plis_used(self, value):
self.json['plis_used'] = value
@property
def progress(self):
percent = int(100 * convert_to_value(self.avail_resources) / convert_to_value(self.cost))
if percent > 100:
return 100
return percent
def enrich_json(self, json):
json['amount'] = self.amount
json['open'] = self.open
class TaskWrapper(JsonWrapper):
......@@ -47,29 +72,26 @@ class TaskWrapper(JsonWrapper):
super().__init__(state, key, TASKS[key], task_json, exp_amount=True)
@property
def plis_used(self):
return self.json.get('plis_used', 0)
def science(self):
return self.state.science(self.config['science'])
@plis_used.setter
def plis_used(self, value):
self.json['plis_used'] = value
@property
def open(self):
return self.science.amount > 0
@property
def production(self):
science_key = self.config['production_science']
science = self.state.science(science_key)
def prod(self):
science = self.science
if science.amount == 0:
return (0, 0)
return convert_to_exp_amount(
self.plis_used * self.config['production_base'] *
self.config['production_exp'] ** (science.amount - 1)
self.plis_used * self.state.plis_boost *
self.config['prod_base'] * self.config['prod_exp'] ** (science.amount - 1)
)
@property
def has_production(self):
science_key = self.config['production_science']
science = self.state.science(science_key)
return science.amount > 0
def enrich_json(self, json):
super().enrich_json(json)
json['prod'] = self.prod
class ScienceWrapper(JsonWrapper):
......@@ -78,28 +100,30 @@ class ScienceWrapper(JsonWrapper):
super().__init__(state, key, SCIENCE[key], task_json)
@property
def required_resource(self):
return TASKS[self.config['task_key']].get('name', '')
def resource(self):
return self.state.task(self.config['resource'])
@property
def open(self):
return self.resource.open
@property
def cost(self):
cost_base = convert_to_value(self.config['cost_base'])
return convert_to_exp_amount(
convert_to_value(self.config.get('cost_base', (1, 0))) *
self.config.get('cost_exp', 2) ** self.amount
cost_base * self.config['cost_exp'] ** self.amount
)
@property
def avail_resources(self):
task = self.state.task(self.config['task_key'])
return task.amount
return self.resource.amount
@property
def progress(self):
task = self.state.task(self.config['task_key'])
ratio = int(100 * convert_to_value(task.amount) / convert_to_value(self.cost))
if ratio > 100:
ratio = 100
return ratio
def enrich_json(self, json):
super().enrich_json(json)
json['resource_name'] = self.resource.name
json['cost'] = self.cost
json['avail_resources'] = self.avail_resources
json['progress'] = self.progress
class UniversityWrapper(JsonWrapper):
......@@ -108,8 +132,17 @@ class UniversityWrapper(JsonWrapper):
super().__init__(state, key, UNIVERSITY[key], university_json, exp_amount=True)
@property
def required_resource(self):
return TASKS[self.config['task_key']].get('name', '')
def previous(self):
if self.config['previous']:
return self.state.university(self.config['previous'])
@property
def resource(self):
return self.state.task(self.config['resource'])
@property
def open(self):
return self.resource.open
@property
def cost(self):
......@@ -117,16 +150,47 @@ class UniversityWrapper(JsonWrapper):
@property
def avail_resources(self):
task = self.state.task(self.config['task_key'])
return task.amount
return self.resource.amount
def enrich_json(self, json):
super().enrich_json(json)
previous = self.previous
json['previous_name'] = None if previous is None else previous.name
json['resource_name'] = self.resource.name
json['cost'] = self.cost
json['avail_resources'] = self.avail_resources
class GrantWrapper(JsonWrapper):
def __init__(self, state, key, grant_json):
super().__init__(state, key, GRANTS[key], grant_json)
@property
def plis_used(self):
return self.json.get('plis_used', 0)
def resource(self):
return self.state.university(self.config['resource'])
@plis_used.setter
def plis_used(self, value):
self.json['plis_used'] = value
@property
def open(self):
return self.resource.open
@property
def cost(self):
cost_base = convert_to_value(self.config['cost_base'])
return convert_to_exp_amount(
cost_base * self.config['cost_exp'] ** self.amount
)
@property
def avail_resources(self):
return self.resource.amount
def enrich_json(self, json):
super().enrich_json(json)
json['resource_name'] = self.resource.name
json['cost'] = self.cost
json['avail_resources'] = self.avail_resources
json['progress'] = self.progress
class StateWrapper:
......@@ -144,22 +208,37 @@ class StateWrapper:
if time_delta <= 0:
return
for task in self.tasks:
for task in self.task_list:
task.amount = convert_to_exp_amount(
convert_to_value(task.amount) +
convert_to_value(task.production) * time_delta
convert_to_value(task.prod) * time_delta
)
for university in self.university_list:
task = self.task(university.config['task_key'])
task_amount = convert_to_value(task.amount)
resource = university.resource
resource_amount = convert_to_value(resource.amount)
university_cost = convert_to_value(university.cost)
max_production = task_amount // university_cost
real_production = min(university.plis_used * time_delta, max_production)
task.amount = convert_to_exp_amount(task_amount - real_production * university_cost)
prod_count = min(
university.plis_used * self.plis_boost * time_delta,
resource_amount // university_cost
)
previous = university.previous
if previous is not None:
previous_amount = convert_to_value(previous.amount)
prod_count = min(
prod_count,
previous_amount
)
resource.amount = convert_to_exp_amount(resource_amount - prod_count * university_cost)
university.amount = convert_to_exp_amount(
convert_to_value(university.amount) + real_production
convert_to_value(university.amount) + prod_count
)
if previous is not None:
previous.amount = convert_to_exp_amount(
previous_amount - prod_count
)
self.instance.state['timestamp'] = new_timestamp
self.instance.save()
......@@ -168,7 +247,7 @@ class StateWrapper:
self.instance.state['exp_char_mode'] = not self.exp_char_mode
self.instance.save()
def use_plis(self, task_key, amount):
def use_plis_task(self, task_key, amount):
if task_key not in TASKS:
return
......@@ -182,12 +261,12 @@ class StateWrapper:
return
science = self.science(science_key)
task = self.task(science.config['task_key'])
resource = science.resource
task_amount = convert_to_value(task.amount)
resource_amount = convert_to_value(resource.amount)
science_cost = convert_to_value(science.cost)
if task_amount >= science_cost:
task.amount = convert_to_exp_amount(task_amount - science_cost)
if resource_amount >= science_cost:
resource.amount = convert_to_exp_amount(resource_amount - science_cost)
science.amount += 1
self.instance.save()
......@@ -200,27 +279,37 @@ class StateWrapper:
university.plis_used += amount
self.instance.save()
def get_grant(self, grant_key):
if grant_key not in GRANTS:
return
grant = self.grant(grant_key)
resource = grant.resource
resource_amount = convert_to_value(resource.amount)
grant_cost = convert_to_value(grant.cost)
if resource_amount >= grant_cost:
resource.amount = convert_to_exp_amount(resource_amount - grant_cost)
grant.amount += 1
self.instance.save()
def to_json(self):
data = copy.deepcopy(self.instance.state)
data['plis'] = self.plis
data['plis_free'] = self.plis_free
data['plis_boost'] = self.plis_boost
for key, task in data.get('tasks', {}).items():
wrapper = self.task(key)
task['amount'] = wrapper.amount
task['production'] = wrapper.production
task['has_production'] = wrapper.has_production
self.task(key).enrich_json(task)
for key, science in data.get('science', {}).items():
wrapper = self.science(key)
science['cost'] = wrapper.cost
science['avail_resources'] = wrapper.avail_resources
science['progress'] = wrapper.progress
self.science(key).enrich_json(science)
for key, university in data.get('university', {}).items():
wrapper = self.university(key)
university['amount'] = wrapper.amount
university['avail_resources'] = wrapper.avail_resources
self.university(key).enrich_json(university)
for key, grant in data.get('grants', {}).items():
self.grant(key).enrich_json(grant)
return data
......@@ -230,17 +319,22 @@ class StateWrapper:
@property
def plis(self):
return self.science('science_1').amount
return sum(self.science(key).amount for key in PLIS_SCIENCES) + 1
@property
def plis_free(self):
free = self.plis
for task in self.tasks:
free -= task.plis_used
for university in self.university_list:
free -= university.plis_used
free -= sum(task.plis_used for task in self.task_list)
free -= sum(university.plis_used for university in self.university_list)
return free
@property
def plis_boost(self):
boost = 1
for grant in self.grant_list:
boost *= (1 + grant.amount)
return boost
def task(self, key):
if 'tasks' not in self.instance.state:
self.instance.state['tasks'] = {}
......@@ -252,7 +346,7 @@ class StateWrapper:
return TaskWrapper(self, key, tasks[key])
@property
def tasks(self):
def task_list(self):
return [
self.task(key)
for key in TASKS
......@@ -292,17 +386,31 @@ class StateWrapper:
for key in UNIVERSITY
]
def grant(self, key):
if 'grants' not in self.instance.state:
self.instance.state['grants'] = {}
grants = self.instance.state['grants']
if key not in grants:
grants[key] = {}
return GrantWrapper(self, key, grants[key])
@property
def grant_list(self):
return [
self.grant(key)
for key in GRANTS
]
def initial_state():
return {
'exp_char_mode': True,
'science': {
'science_0': {
's1': {
'amount': 1
},
'science_1': {
'amount': 1
}
},
}
......
......@@ -7,9 +7,10 @@ urlpatterns = [
path('', views.index, name='index'),
path('update/', views.update, name='update'),
path('toggle_char_mode/', views.toggle_char_mode, name='toggle_char_mode'),
path('use_plis/<task_key>/<amount>', views.use_plis, name='use_plis'),
path('use_plis_task/<task_key>/<amount>', views.use_plis_task, name='use_plis_task'),
path('do_research/<science_key>', views.do_research, name='do_research'),
path('use_plis_university/<university_key>/<amount>', views.use_plis_university, name='use_plis_university'),
path('get_grant/<grant_key>', views.get_grant, name='get_grant'),
path('debug_wipe/', debug_views.debug_wipe, name='debug_wipe'),
path('debug_skip_time/<int:seconds>', debug_views.debug_skip_time, name='debug_skip_time'),
]
......@@ -8,13 +8,3 @@ def convert_to_exp_amount(value):
def convert_to_value(exp_amount):
return exp_amount[0] * 1000 ** exp_amount[1]
def normalize_exp_amount(value, exp):
while value >= 1e6:
value //= 1000
exp += 1
while value < 1e3 and exp > 0:
value *= 1000
exp -= 1
return value, exp
......@@ -27,10 +27,17 @@ def toggle_char_mode(request):
@login_required
def use_plis(request, task_key, amount):
def use_plis_task(request, task_key, amount):
amount = int(amount)
state = get_state(request.user)
state.use_plis(task_key, amount)
state.use_plis_task(task_key, amount)
return JsonResponse(state.to_json())
@login_required
def do_research(request, science_key):
state = get_state(request.user)
state.do_research(science_key)
return JsonResponse(state.to_json())
......@@ -43,7 +50,7 @@ def use_plis_university(request, university_key, amount):
@login_required
def do_research(request, science_key):
def get_grant(request, grant_key):
state = get_state(request.user)
state.do_research(science_key)
state.get_grant(grant_key)
return JsonResponse(state.to_json())
......@@ -36,8 +36,8 @@ function renderExpAmount(expAmount) {
}
function renderTask(key, task) {
if (task.has_production != null) {