Update app.py
Browse files
app.py
CHANGED
@@ -1,8 +1,3 @@
|
|
1 |
-
from flask import Flask, render_template, request, redirect, url_for, session
|
2 |
-
import random
|
3 |
-
|
4 |
-
app = Flask(__name__)
|
5 |
-
app.secret_key = 'your_secret_key_here' # セッションの安全な署名に必要なキー
|
6 |
|
7 |
questions:dict[str,float]={
|
8 |
"MgCl2": 95.0,
|
@@ -263,31 +258,168 @@ questions:dict[str,float]={
|
|
263 |
"Al(CH3COO)2": 145.0,
|
264 |
"Al(MnO4)2": 265.0,
|
265 |
}
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
|
275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
|
|
|
|
|
277 |
if request.method == 'POST':
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
result = '不正解です。正解は{}です。'.format(session['current_answer'])
|
283 |
-
|
284 |
-
return render_template('quiz.html', question=session['current_question'], result=result)
|
285 |
|
286 |
-
@app.route('/
|
287 |
-
def
|
288 |
-
|
289 |
-
session.pop('current_answer')
|
290 |
-
return redirect(url_for('quiz'))
|
291 |
|
292 |
if __name__ == '__main__':
|
293 |
-
app.run(debug=True,
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
questions:dict[str,float]={
|
3 |
"MgCl2": 95.0,
|
|
|
258 |
"Al(CH3COO)2": 145.0,
|
259 |
"Al(MnO4)2": 265.0,
|
260 |
}
|
261 |
+
from flask import Flask, render_template, request, redirect, url_for, session
|
262 |
+
import random
|
263 |
+
import sympy as sp
|
264 |
|
265 |
+
app = Flask(__name__)
|
266 |
+
app.secret_key = 'your_secret_key' # セッションのための秘密鍵
|
267 |
+
|
268 |
+
# シンボルの定義と説明
|
269 |
+
symbols_info = {
|
270 |
+
'solute_mass': '溶質の質量 (g)',
|
271 |
+
'solution_mass': '溶液の質量 (g)',
|
272 |
+
'moles_of_solute': '溶質のモル数 (mol)',
|
273 |
+
'volume_of_solution': '溶液の体積 (L)',
|
274 |
+
'mass': '質量 (g)',
|
275 |
+
'volume': '体積 (mL)',
|
276 |
+
'density': '密度 (g/mL)',
|
277 |
+
'molarity': 'モル濃度 (mol/L)',
|
278 |
+
'mass_percent': '質量パーセント濃度 (%)'
|
279 |
+
}
|
280 |
+
|
281 |
+
solute_mass, solution_mass, moles_of_solute, volume_of_solution, mass, volume, density, molarity, mass_percent = sp.symbols(
|
282 |
+
'solute_mass solution_mass moles_of_solute volume_of_solution mass volume density molarity mass_percent')
|
283 |
+
|
284 |
+
# 質量パーセント濃度を計算する関数
|
285 |
+
def calculate_mass_percent(solute_mass, solution_mass):
|
286 |
+
mass_percent = (solute_mass / solution_mass) * 100
|
287 |
+
return round(float(mass_percent), 3)
|
288 |
+
|
289 |
+
def find_mass_percent_value(solute_mass_value, solution_mass_value):
|
290 |
+
equation = sp.Eq(mass_percent, (solute_mass / solution_mass) * 100)
|
291 |
+
result = sp.solve(equation.subs({solute_mass: solute_mass_value, solution_mass: solution_mass_value}), mass_percent)
|
292 |
+
return round(float(result[0]), 3)
|
293 |
+
|
294 |
+
# モル濃度を計算する関数
|
295 |
+
def calculate_molarity(moles_of_solute, volume_of_solution):
|
296 |
+
molarity = moles_of_solute / volume_of_solution
|
297 |
+
return round(float(molarity), 3)
|
298 |
+
|
299 |
+
def find_molarity_value(moles_of_solute_value, volume_of_solution_value):
|
300 |
+
equation = sp.Eq(molarity, moles_of_solute / volume_of_solution)
|
301 |
+
result = sp.solve(equation.subs({moles_of_solute: moles_of_solute_value, volume_of_solution: volume_of_solution_value}), molarity)
|
302 |
+
return round(float(result[0]), 3)
|
303 |
+
|
304 |
+
# 密度を計算する関数
|
305 |
+
def calculate_density(mass, volume):
|
306 |
+
density = mass / volume
|
307 |
+
return round(float(density), 3)
|
308 |
+
|
309 |
+
def find_density_value(mass_value, volume_value):
|
310 |
+
equation = sp.Eq(density, mass / volume)
|
311 |
+
result = sp.solve(equation.subs({mass: mass_value, volume: volume_value}), density)
|
312 |
+
return round(float(result[0]), 3)
|
313 |
+
|
314 |
+
# 循環小数をチェックする関数
|
315 |
+
def is_recurring(decimal_str):
|
316 |
+
if '.' in decimal_str:
|
317 |
+
fractional_part = decimal_str.split('.')[1]
|
318 |
+
for i in range(1, len(fractional_part)):
|
319 |
+
if fractional_part[:i] == fractional_part[i:2*i]:
|
320 |
+
return True
|
321 |
+
return False
|
322 |
+
|
323 |
+
# 問題文テンプレート生成関数
|
324 |
+
def generate_problem_statement(method_name, param_values):
|
325 |
+
templates = {
|
326 |
+
'calculate_mass_percent': [
|
327 |
+
"溶質の質量が {solute_mass} g で、溶液の質量が {solution_mass} g の場合、質量パーセント濃度を求めなさい。",
|
328 |
+
"質量パーセント濃度が {mass_percent}% で、溶液の質量が {solution_mass} g の場合、溶質の質量を求めなさい。",
|
329 |
+
"質量パーセント濃度が {mass_percent}% で、溶質の質量が {solute_mass} g の場合、溶液の質量を求めなさい。"
|
330 |
+
],
|
331 |
+
'calculate_molarity': [
|
332 |
+
"溶質のモル数が {moles_of_solute} mol で、溶液の体積が {volume_of_solution} L の場合、モル濃度を求めなさい。",
|
333 |
+
"モル濃度が {molarity} mol/L で、溶液の体積が {volume_of_solution} L の場合、溶質のモル数を求めなさい。",
|
334 |
+
"モル濃度が {molarity} mol/L で、溶質のモル数が {moles_of_solute} mol の場合、溶液の体積を求めなさい。"
|
335 |
+
],
|
336 |
+
'calculate_density': [
|
337 |
+
"質量が {mass} g で、体積が {volume} mL の場合、密度を求めなさい。",
|
338 |
+
"密度が {density} g/mL で、体積が {volume} mL の場合、質量を求めなさい。",
|
339 |
+
"密度が {density} g/mL で、質量が {mass} g の場合、体積を求めなさい。"
|
340 |
+
]
|
341 |
+
}
|
342 |
+
template_list = templates.get(method_name, ["問題文の生成に失敗しました。"])
|
343 |
+
template = random.choice(template_list)
|
344 |
+
return template.format(**param_values)
|
345 |
+
|
346 |
+
# 公式生成関数
|
347 |
+
def generate_equation_string(method_name, param_values):
|
348 |
+
try:
|
349 |
+
equations = {
|
350 |
+
'calculate_mass_percent': "質量パーセント濃度 = (溶質の質量 / 溶液の質量) * 100\n質量パーセント濃度 = ({solute_mass} / {solution_mass}) * 100".format(**param_values),
|
351 |
+
'calculate_molarity': "モル濃度 = 溶質のモル数 / 溶液の体積\nモル濃度 = {moles_of_solute} / {volume_of_solution}".format(**param_values),
|
352 |
+
'calculate_density': "密度 = 質量 / 体積\n密度 = {mass} / {volume}".format(**param_values),
|
353 |
+
}
|
354 |
+
return equations.get(method_name, "公式の生成に失敗しました。")
|
355 |
+
except KeyError as e:
|
356 |
+
return f"公式の生成中にエラーが発生しました: {e}"
|
357 |
+
|
358 |
+
# 乱数を用いて計算方法を決定し問題を作成する関数
|
359 |
+
def generate_problem():
|
360 |
+
methods = [
|
361 |
+
('calculate_mass_percent', ['solute_mass', 'solution_mass', 'mass_percent']),
|
362 |
+
('calculate_molarity', ['moles_of_solute', 'volume_of_solution', 'molarity']),
|
363 |
+
('calculate_density', ['mass', 'volume', 'density']),
|
364 |
+
]
|
365 |
|
366 |
+
while True:
|
367 |
+
method_name, params = random.choice(methods)
|
368 |
+
param_values = {param: random.randint(1, 100) for param in params}
|
369 |
+
|
370 |
+
missing_param = random.choice(params)
|
371 |
+
param_values[missing_param] = 'x'
|
372 |
+
|
373 |
+
equation = generate_equation_string(method_name, param_values).split('\n')[1]
|
374 |
+
|
375 |
+
solution = solve_equation(equation, 'x')
|
376 |
+
|
377 |
+
if solution and all(isinstance(s, (int, float)) for s in solution):
|
378 |
+
solution_value = round(float(solution[0]), 16)
|
379 |
+
solution_str = f'{solution_value:.16f}'
|
380 |
+
if is_recurring(solution_str):
|
381 |
+
continue
|
382 |
+
if len(str(solution_value).split('.')[1]) <= 4:
|
383 |
+
break
|
384 |
+
|
385 |
+
param_values[missing_param] = solution_value
|
386 |
+
|
387 |
+
problem_statement = generate_problem_statement(method_name, param_values)
|
388 |
+
equation_string = generate_equation_string(method_name, param_values)
|
389 |
+
return method_name, param_values, solution_value, problem_statement, equation_string
|
390 |
+
|
391 |
+
@app.route('/', methods=['GET', 'POST'])
|
392 |
+
def index():
|
393 |
+
if request.method == 'POST':
|
394 |
+
try:
|
395 |
+
user_input = float(request.form['user_input'])
|
396 |
+
solution = float(request.form['solution'])
|
397 |
+
correct = abs(user_input - solution) < 1e-3
|
398 |
+
except ValueError:
|
399 |
+
correct = False
|
400 |
+
user_input = None
|
401 |
+
solution = None
|
402 |
+
return render_template('result.html', correct=correct, user_input=user_input, solution=solution, problem_statement=session.get('problem_statement'), equation_string=session.get('equation_string'))
|
403 |
+
else:
|
404 |
+
method_name, param_values, solution, problem_statement, equation_string = generate_problem()
|
405 |
+
session['problem_statement'] = problem_statement
|
406 |
+
session['solution'] = solution
|
407 |
+
session['method_name'] = method_name
|
408 |
+
session['param_values'] = param_values
|
409 |
+
session['equation_string'] = equation_string
|
410 |
+
return render_template('index.html', method_name=method_name, param_values=param_values, solution=solution, problem_statement=problem_statement, symbols_info=symbols_info)
|
411 |
|
412 |
+
@app.route('/retry', methods=['GET', 'POST'])
|
413 |
+
def retry():
|
414 |
if request.method == 'POST':
|
415 |
+
return redirect(url_for('index'))
|
416 |
+
if 'method_name' not in session or 'param_values' not in session or 'solution' not in session or 'problem_statement' not in session or 'equation_string' not in session:
|
417 |
+
return redirect(url_for('index'))
|
418 |
+
return render_template('index.html', method_name=session.get('method_name'), param_values=session.get('param_values'), solution=session.get('solution'), problem_statement=session.get('problem_statement'), symbols_info=symbols_info, equation_string=session.get('equation_string'))
|
|
|
|
|
|
|
419 |
|
420 |
+
@app.route('/new')
|
421 |
+
def new_problem():
|
422 |
+
return redirect(url_for('index'))
|
|
|
|
|
423 |
|
424 |
if __name__ == '__main__':
|
425 |
+
app.run(debug=True, host="0.0.0.0", port=7860)
|