OK much
This commit is contained in:
Binary file not shown.
10
Html/app.log
Normal file
10
Html/app.log
Normal file
@@ -0,0 +1,10 @@
|
||||
/home/caikecheng/anaconda3/envs/algoAgent/lib/python3.10/site-packages/pydantic/_internal/_config.py:345: UserWarning: Valid config keys have changed in V2:
|
||||
* 'fields' has been removed
|
||||
warnings.warn(message, UserWarning)
|
||||
2024-12-28 22:52:57.446 | INFO | agentscope.models:read_model_configs:186 - Load configs for model wrapper: openai_cfg
|
||||
Traceback (most recent call last):
|
||||
File "/home/caikecheng/algoAgent/code-agent/Html/app.py", line 343, in <module>
|
||||
socketio.run(app, host='0.0.0.0', port=5000, debug=True)
|
||||
File "/home/caikecheng/anaconda3/envs/algoAgent/lib/python3.10/site-packages/flask_socketio/__init__.py", line 640, in run
|
||||
raise RuntimeError('The Werkzeug web server is not '
|
||||
RuntimeError: The Werkzeug web server is not designed to run in production. Pass allow_unsafe_werkzeug=True to the run() method to disable this error.
|
||||
176
Html/app.py
176
Html/app.py
@@ -9,10 +9,24 @@ import sys
|
||||
import json
|
||||
parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
sys.path.insert(0, parent_dir)
|
||||
student_workspace_root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../study'))
|
||||
current_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '.'))
|
||||
sys.path.insert(0, current_dir)
|
||||
from AlgoriAgent.projects.algoriAgent.agent_manager import AgentManager
|
||||
|
||||
|
||||
import configparser
|
||||
|
||||
from db.user_list import UserList
|
||||
from db.user import User, load_user_from_json, create_user_json
|
||||
from db.course_list import CourseList
|
||||
from db.course import Course, load_course_from_json
|
||||
GLOBAL_CONFIG = configparser.ConfigParser()
|
||||
GLOBAL_CONFIG.read('config.ini')
|
||||
VSCODE_WEB_URL = GLOBAL_CONFIG['VSCODE_WEB']['url']
|
||||
USER_DATA_DIR = GLOBAL_CONFIG['USER_DATA']['dir']
|
||||
COURSE_DATA_DIR = GLOBAL_CONFIG['COURSE_DATA']['dir']
|
||||
|
||||
app = Flask(__name__)
|
||||
socketio = SocketIO(app, cors_allowed_origins="*",ping_timeout=60, ping_interval=5)
|
||||
# socketio = SocketIO(app, cors_allowed_origins="http://localhost:9888") # 设置跨域支持
|
||||
@@ -20,7 +34,7 @@ import logging
|
||||
app.secret_key = 'cakebaker'
|
||||
app.logger.setLevel(logging.DEBUG)
|
||||
# 配置 CORS
|
||||
CORS(app, resources={r"/*": {"origins": "http://127.0.0.1:9090"},}, supports_credentials=True)
|
||||
CORS(app, resources={r"/*": {"origins": VSCODE_WEB_URL},}, supports_credentials=True)
|
||||
|
||||
|
||||
userid_recorder = {} # user_id&path -> session['user_id']
|
||||
@@ -31,8 +45,8 @@ Backboard
|
||||
from backboardManager import BackBoardManager, Backboard
|
||||
|
||||
backboard_manager = BackBoardManager()
|
||||
uuid2user_id = {}
|
||||
user_id2uuid = {}
|
||||
uuid2username = {}
|
||||
username2uuid = {}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +59,7 @@ class VSCodeNamespace(Namespace):
|
||||
user_id = dataconfig.get('user_id')
|
||||
path = dataconfig.get('path')
|
||||
print(f"User {user_id} connected with path: {path}")
|
||||
useruuid = user_id2uuid[user_id]
|
||||
useruuid = username2uuid[user_id]
|
||||
join_room(useruuid, namespace='/vscode')
|
||||
if backboard_manager.get_backboard(useruuid) == None:
|
||||
backboard_manager.add_backboard(useruuid, path)
|
||||
@@ -56,14 +70,15 @@ class VSCodeNamespace(Namespace):
|
||||
dataconfig = data['config']
|
||||
realtime_response(dataconfig, data)
|
||||
# emit('response', {'message': 'Config data received and connection established'})
|
||||
def on_disconnect(self):
|
||||
def on_disconnect(self, data):
|
||||
print("VSCode client disconnected")
|
||||
print("Disconnect reason:"+str(data))
|
||||
|
||||
|
||||
def realtime_response(config, realtime_action):
|
||||
user_id = config['user_id']
|
||||
folder_path = config['path']
|
||||
useruuid = user_id2uuid[user_id]
|
||||
useruuid = username2uuid[user_id]
|
||||
bb = backboard_manager.get_backboard(useruuid)
|
||||
assert type(bb) == Backboard
|
||||
|
||||
@@ -75,14 +90,12 @@ def realtime_response(config, realtime_action):
|
||||
if realtime_action['type'] == 'activeFile':
|
||||
file_path = realtime_action['filePath']
|
||||
assert type(file_path) == str
|
||||
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
|
||||
bb.active_file_path = file_path
|
||||
with open(f"../{user_id}/{folder_path}/{file_path}") as f:
|
||||
with open(f"{file_path}") as f:
|
||||
bb.active_file_content = f.read()
|
||||
|
||||
if realtime_action['type'] == 'paste':
|
||||
file_path = realtime_action['filePath']
|
||||
file_path = "".join(file_path.split(f'/{user_id}/{folder_path}/')[1:])
|
||||
file_path = realtime_action['filePath']
|
||||
assert type(file_path) == str
|
||||
bb.pasted_file_path = file_path
|
||||
bb.pasted_content = realtime_action['content']
|
||||
|
||||
@@ -106,21 +119,22 @@ class AgentNamespace(Namespace):
|
||||
def on_login(self, data):
|
||||
data = json.loads(data)
|
||||
user = data['username']
|
||||
folder_name = data['folder']
|
||||
user_uuid = user_id2uuid[user]
|
||||
course_id = data['course_id']
|
||||
chapter_id = data['chapter_id']
|
||||
user_uuid = username2uuid[user]
|
||||
session['user_id'] = user_uuid
|
||||
print(f'User connected with session user_id: {user_uuid}')
|
||||
# 从markdown、markdown_prompts、score_prompts中各读取数据folder.md并进行new_agent
|
||||
with open(f'books/markdown/{folder_name}.md','r',encoding='UTF-8') as fmd,\
|
||||
open(f'books/markdown_prompts/{folder_name}.md','r',encoding='UTF-8')as fmdp,\
|
||||
open(f'books/score_prompts/{folder_name}.md','r',encoding='UTF-8') as fsp:
|
||||
with open(f'books/markdown/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fmd,\
|
||||
open(f'books/markdown_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8')as fmdp,\
|
||||
open(f'books/score_prompts/{course_id}/{chapter_id}.md','r',encoding='UTF-8') as fsp:
|
||||
markdown = fmd.read()
|
||||
markdown_prompts = fmdp.read()
|
||||
score_prompts = fsp.read()
|
||||
user_uuid, agent = agent_manager.new_agent(markdown, markdown_prompts, score_prompts, id=user_uuid, root_path=f'{user}/{folder_name}')
|
||||
user_uuid, agent = agent_manager.new_agent(course_id, chapter_id, markdown, markdown_prompts, score_prompts, id=user_uuid, root_path=f'{user}/{course_id}/{chapter_id}')
|
||||
print(user_uuid)
|
||||
join_room(user_uuid, namespace='/agent') # 将该用户加入以user_id为名的room
|
||||
backboard_manager.add_backboard(user_uuid, folder_name)
|
||||
backboard_manager.add_backboard(user_uuid, chapter_id)
|
||||
|
||||
def on_language(self, language):
|
||||
id = session.get('user_id')
|
||||
@@ -154,8 +168,9 @@ class AgentNamespace(Namespace):
|
||||
agent_manager.function_call(id, data['data'])
|
||||
|
||||
|
||||
def on_disconnect(self):
|
||||
def on_disconnect(self,data):
|
||||
print("VSCode client disconnected")
|
||||
print("Disconnect reason:"+str(data))
|
||||
|
||||
|
||||
|
||||
@@ -169,9 +184,9 @@ IMAGE_DIR = 'image' # 图片资源相对于 markdown 的位置
|
||||
|
||||
|
||||
|
||||
@app.route('/<filename>-markdown', methods=['GET'])
|
||||
def convert_md(filename):
|
||||
md_file_path = os.path.join(MARKDOWN_DIR, f'{filename}.md')
|
||||
@app.route('/<course_id>-<filename>-markdown', methods=['GET'])
|
||||
def convert_md(course_id, filename):
|
||||
md_file_path = os.path.join(MARKDOWN_DIR,course_id, f'{filename}.md')
|
||||
|
||||
if not os.path.exists(md_file_path):
|
||||
return jsonify({'error': 'Markdown file not found'}), 404
|
||||
@@ -205,7 +220,7 @@ def convert_md(filename):
|
||||
html_file.write(html_with_styles)
|
||||
|
||||
# 处理图片资源,将 image/xxx 文件夹拷贝到 static/image/xxx
|
||||
image_source_dir = os.path.join(MARKDOWN_DIR, IMAGE_DIR, filename)
|
||||
image_source_dir = os.path.join(MARKDOWN_DIR,course_id, IMAGE_DIR, filename)
|
||||
image_target_dir = os.path.join(STATIC_DIR, IMAGE_DIR, filename)
|
||||
print(f"Copying image resources from {image_source_dir} to {image_target_dir}")
|
||||
if os.path.exists(image_source_dir):
|
||||
@@ -230,25 +245,35 @@ def serve_static(filename):
|
||||
'''
|
||||
Vscode
|
||||
'''
|
||||
@app.route('/desktop/<user_id>/<path>')
|
||||
def hello_world(user_id, path):
|
||||
@app.route('/desktop/<user_id>/<course_id>/<chapter_id>')
|
||||
def desktop(user_id, course_id, chapter_id):
|
||||
if 'user_id' not in session:
|
||||
# return redirect(url_for('login'))
|
||||
session['user_id'] = 'user_' + str(uuid.uuid4())
|
||||
print("user "+ user_id + "uuid is"+ session['user_id'])
|
||||
user_id2uuid[user_id] = session['user_id']
|
||||
uuid2user_id[session['user_id']] = user_id
|
||||
userid_recorder[user_id+'&'+path] = session['user_id']
|
||||
username2uuid[user_id] = session['user_id']
|
||||
uuid2username[session['user_id']] = user_id
|
||||
userid_recorder[user_id+'&'+course_id] = session['user_id']
|
||||
|
||||
# 在上层 目录下创建一个名为 user_id_path 的文件夹
|
||||
path_dir = os.path.join(parent_dir, user_id, path)
|
||||
# 在学习目录下创建一个名为 user_id_path 的文件夹
|
||||
path_dir = os.path.join(student_workspace_root_path, user_id, course_id,chapter_id)
|
||||
os.makedirs(path_dir, exist_ok=True)
|
||||
# 在此文件夹内部创建一个.config文件,并写入 user_id=user_id\n path=path
|
||||
config_path = os.path.join(path_dir, '.config')
|
||||
print('---------------------')
|
||||
print(config_path)
|
||||
with open(config_path, 'w') as f:
|
||||
f.write(f"user_id={user_id}\npath={path}")
|
||||
return render_template('desktop.html', user_id=user_id, path=path)
|
||||
tmpd = {'user_id': user_id, 'course_id': course_id, 'chapter_id': chapter_id, 'path': path_dir}
|
||||
json.dump(tmpd, f)
|
||||
return render_template('desktop.html', vscode_web_url=VSCODE_WEB_URL, user_id=user_id, course_id=course_id, chapter_id=chapter_id, workspace_path=path_dir)
|
||||
|
||||
@app.route('/desktop_nouser/<course_id>/<chapter_id>')
|
||||
def desktop_nouser(course_id, chapter_id):
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('login'))
|
||||
user_id = session['user_id']
|
||||
username = uuid2username[user_id]
|
||||
return redirect(url_for('desktop', user_id=username, course_id=course_id, chapter_id=chapter_id))
|
||||
|
||||
@app.route('/vscode_data', methods=['POST'])
|
||||
def vscode_data():
|
||||
@@ -269,17 +294,33 @@ def get_session():
|
||||
Login
|
||||
|
||||
'''
|
||||
users_list = UserList()
|
||||
course_list = CourseList()
|
||||
|
||||
@app.route('/register')
|
||||
def register():
|
||||
return render_template('register.html')
|
||||
|
||||
@app.route('/register_post', methods=['POST'])
|
||||
def register_post():
|
||||
data = request.get_json()
|
||||
username = data.get('username')
|
||||
password = data.get('password')
|
||||
if users_list.has_user(username) is not None:
|
||||
users_list.add_user(username, password)
|
||||
create_user_json(username, USER_DATA_DIR)
|
||||
return jsonify({'success': True, 'message': '注册成功'})
|
||||
else: return jsonify({'success': False, 'message': '用户已存在,请更换用户名'})
|
||||
|
||||
|
||||
@app.route('/login')
|
||||
def login():
|
||||
return render_template('login.html')
|
||||
if 'user_id' not in session:
|
||||
return render_template('login.html')
|
||||
else:
|
||||
return redirect(url_for('/'))
|
||||
|
||||
from db.user_list import UserList
|
||||
users_list = UserList()
|
||||
|
||||
@app.route('/login_post', methods=['POST'])
|
||||
def login_post():
|
||||
# 获取请求的 JSON 数据
|
||||
@@ -288,42 +329,79 @@ def login_post():
|
||||
username = data.get('username')
|
||||
password = data.get('password')
|
||||
|
||||
user = users_list.get_user(username)
|
||||
if user is None:
|
||||
return jsonify({'success': False, 'message': '用户名或密码错误'})
|
||||
pswd = users_list.get_user_pswd(username)
|
||||
|
||||
if user['password'] != password:
|
||||
if pswd is None:
|
||||
return jsonify({'success': False, 'message': '用户名或密码错误'})
|
||||
if pswd != password:
|
||||
return jsonify({'success': False, 'message': '用户名或密码错误'})
|
||||
|
||||
session['user_id'] = 'user_' + str(uuid.uuid4())
|
||||
print("user "+ username + "uuid is"+ session['user_id'])
|
||||
user_id2uuid[username] = session['user_id']
|
||||
uuid2user_id[session['user_id']] = username
|
||||
username2uuid[username] = session['user_id']
|
||||
uuid2username[session['user_id']] = username
|
||||
return jsonify({'success': True, 'message': '登录成功'})
|
||||
|
||||
|
||||
user_id2UserClass = {}
|
||||
'''
|
||||
DashBoard
|
||||
'''
|
||||
@app.route('/dashboard')
|
||||
def dashboard():
|
||||
if 'user_id' not in session:
|
||||
if 'user_id' not in session or session['user_id'] not in uuid2username:
|
||||
return redirect(url_for('login'))
|
||||
return render_template('dashboard.html')
|
||||
user_id = session['user_id']
|
||||
username = uuid2username[user_id]
|
||||
if (user_id not in user_id2UserClass):
|
||||
user_id2UserClass[user_id] = load_user_from_json(username, user_data_dir = USER_DATA_DIR)
|
||||
user_course_data = []
|
||||
for course_id in user_id2UserClass[user_id].select_course:
|
||||
course_brief_info = course_list.get_course_brief_info(course_id, load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR))
|
||||
user_course_data.append(course_brief_info)
|
||||
return render_template('dashboard.html',user_data = json.dumps(user_id2UserClass[user_id].__json__()), user_course_data = json.dumps(user_course_data))
|
||||
|
||||
'''
|
||||
Book
|
||||
Course
|
||||
'''
|
||||
|
||||
@app.route('/book/<book_name>')
|
||||
def book(book_name):
|
||||
return render_template('book.html', book_name=book_name)
|
||||
@app.route('/course/<course_id>')
|
||||
def course(course_id):
|
||||
c = load_course_from_json(course_id, course_data_dir = COURSE_DATA_DIR)
|
||||
return render_template('course.html', course_id=course_id, course_data=c)
|
||||
|
||||
@app.route('/select_course', methods=['POST'])
|
||||
def select_course():
|
||||
if ('user_id' not in session or session['user_id'] not in user_id2UserClass):return redirect(url_for('login'))
|
||||
user = user_id2UserClass[session['user_id']]
|
||||
data = request.get_json()
|
||||
course_id = data.get('course_id')
|
||||
if course_id:
|
||||
user.select_new_course(course_id, load_course_from_json(course_id, COURSE_DATA_DIR))
|
||||
return jsonify({'success': True, 'message': '课程选择成功'})
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def home_index():
|
||||
return render_template('index.html')
|
||||
selected_courses=[]
|
||||
if ('user_id' in session):
|
||||
if (session['user_id'] not in user_id2UserClass): return redirect(url_for('login'))
|
||||
user = user_id2UserClass[session['user_id']]
|
||||
for course_id in user.select_course:
|
||||
selected_courses.append(course_id)
|
||||
|
||||
return render_template('index.html', courses_data = course_list, selected_courses =selected_courses)
|
||||
|
||||
# 一些app辅助函数,主要提供给Agent与数据库的交互能力
|
||||
|
||||
class MyFunction:
|
||||
def save_chapter_memory(self, id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal):
|
||||
print("-=-=-=-=-=-=-=-")
|
||||
print(id, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
|
||||
username = uuid2username[id]
|
||||
u = load_user_from_json(username, user_data_dir = USER_DATA_DIR)
|
||||
u.save_chapter_memory(course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal)
|
||||
|
||||
app.my_function = MyFunction()
|
||||
if __name__ == '__main__':
|
||||
socketio.on_namespace(VSCodeNamespace('/vscode'))
|
||||
socketio.on_namespace(AgentNamespace('/agent'))
|
||||
|
||||
@@ -30,4 +30,4 @@
|
||||
|
||||
本体测试点文件夹名 `twice_split。`
|
||||
|
||||
_require_tools=judge
|
||||
_require_tools=judge,algorithm,binary_search,binary_search
|
||||
@@ -14,3 +14,10 @@ listen_port = 3001
|
||||
server_address = ws://localhost:3000/myService
|
||||
agent_process_provider_host = localhost
|
||||
agent_process_provider_port = 3002
|
||||
|
||||
[VSCODE_WEB]
|
||||
url = http://59.78.194.131:9090
|
||||
[USER_DATA]
|
||||
dir = db/data/user/
|
||||
[COURSE_DATA]
|
||||
dir = db/data/course/
|
||||
42
Html/db/course.py
Normal file
42
Html/db/course.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import os
|
||||
# Example usage:
|
||||
import json
|
||||
LOCAL_COURSE_DATA_DIR = "data/course/" # only use locally, not for other .py files
|
||||
|
||||
class Course:
|
||||
def __init__(self, course_name, course_id, course_auther, course_img_path, lessons, description):
|
||||
self.course_name = course_name
|
||||
self.course_id = course_id
|
||||
self.course_auther = course_auther
|
||||
self.course_img_path = course_img_path
|
||||
self.lessons = lessons
|
||||
self.description = description
|
||||
|
||||
|
||||
def __json__(self):
|
||||
return {
|
||||
'course_id': self.course_id,
|
||||
'course_name': self.course_name,
|
||||
'course_auther': self.course_auther,
|
||||
'course_img_path': self.course_img_path,
|
||||
'lessons': self.lessons,
|
||||
'description': self.description
|
||||
}
|
||||
def to_json(self):
|
||||
return json.dumps(self, default=lambda o: o.__json__(), indent=4)
|
||||
|
||||
def load_course_from_json(course_id, course_data_dir = None)-> Course:
|
||||
try:
|
||||
COURSE_DATA_DIR = course_data_dir if course_data_dir else LOCAL_COURSE_DATA_DIR
|
||||
with open(os.path.join(COURSE_DATA_DIR, f'{course_id}.json'), "r") as f:
|
||||
raw_json = f.read()
|
||||
user_data = json.loads(raw_json)
|
||||
return Course(**user_data)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
if(__name__ == "__main__"):
|
||||
|
||||
user = load_course_from_json('CS101')
|
||||
|
||||
@@ -1,105 +1,62 @@
|
||||
import os
|
||||
from tinydb import TinyDB, Query, where
|
||||
|
||||
import json
|
||||
import copy
|
||||
import re
|
||||
class CourseList:
|
||||
def __init__(self, db_file='db/data/course/course_list.json'):
|
||||
"""初始化课程列表,自动打开并加载 JSON 数据文件。"""
|
||||
self.db_file = db_file
|
||||
self.db = TinyDB(self.db_file)
|
||||
self.course_query = Query()
|
||||
with open(self.db_file, 'r') as f:
|
||||
self.db = json.load(f)
|
||||
|
||||
def add_course(self, course_data):
|
||||
"""添加新的课程到课程列表。"""
|
||||
if not self.db.search(self.course_query.course_id == course_data['course_id']):
|
||||
self.db.insert(course_data)
|
||||
else:
|
||||
print(f"Course with ID {course_data['course_id']} already exists.")
|
||||
def add_course(self, course_id, course_name, course_create_date, course_update_data, course_img_path):
|
||||
"""添加新的用户登录信息"""
|
||||
# 检查是否已经有该用户
|
||||
assert course_id not in self.db, f"Course {course_name} with ID {course_id} already exists."
|
||||
self.db[course_id] = {}
|
||||
self.db[course_id]['course_name'] = course_name
|
||||
self.db[course_id]['course_create_date'] = course_create_date
|
||||
self.db[course_id]['course_update_data'] = course_update_data
|
||||
self.db[course_id]['course_img_path'] = course_img_path
|
||||
|
||||
def get_course(self, course_id):
|
||||
"""获取指定 course_id 的课程信息。"""
|
||||
result = self.db.search(self.course_query.course_id == course_id)
|
||||
return result[0] if result else None
|
||||
with open(self.db_file, 'w') as f:
|
||||
json.dump(self.db, f, indent=4)
|
||||
|
||||
def update_course(self, course_id, updated_data):
|
||||
"""更新指定 course_id 的课程信息。"""
|
||||
self.db.update(updated_data, self.course_query.course_id == course_id)
|
||||
|
||||
def get_course_brief_info(self, course_id, course) -> dict:
|
||||
assert course_id in self.db, f"Course ID {course_id} does not exist."
|
||||
result = copy.deepcopy(self.db[course_id])
|
||||
result["lessons"]=[]
|
||||
for lesson in course.lessons:
|
||||
d={}
|
||||
d['lesson_id'] = lesson['lesson_id']
|
||||
d["lesson_name"]=lesson['lesson_name']
|
||||
print(lesson["markdown"])
|
||||
h3_titles = re.findall(r'[\s]###\s+(.*)', lesson["markdown"])
|
||||
print(h3_titles)
|
||||
d["subChapters"]=h3_titles
|
||||
result["lessons"].append(d)
|
||||
return result
|
||||
|
||||
def update_course_brief_info(self, course_id, course_name, course_create_date, course_update_data, course_img_path):
|
||||
assert course_id in self.db, f"Course ID {course_id} does not exist."
|
||||
|
||||
self.db[course_id]['course_name'] = course_name
|
||||
self.db[course_id]['course_create_date'] = course_create_date
|
||||
self.db[course_id]['course_update_data'] = course_update_data
|
||||
self.db[course_id]['course_img_path'] = course_img_path
|
||||
|
||||
with open(self.db_file, 'w') as f:
|
||||
json.dump(self.db, f, indent=4)
|
||||
|
||||
def delete_course(self, course_id):
|
||||
"""删除指定 course_id 的课程。"""
|
||||
self.db.remove(self.course_query.course_id == course_id)
|
||||
|
||||
def add_lesson_to_course(self, course_id, lesson_data):
|
||||
"""为指定课程添加课时。"""
|
||||
course = self.get_course(course_id)
|
||||
if course:
|
||||
if 'lessons' not in course:
|
||||
course['lessons'] = []
|
||||
course['lessons'].append(lesson_data)
|
||||
self.update_course(course_id, {'lessons': course['lessons']})
|
||||
else:
|
||||
print(f"Course with ID {course_id} not found.")
|
||||
|
||||
def get_lessons_of_course(self, course_id):
|
||||
"""获取指定课程的所有课时信息。"""
|
||||
course = self.get_course(course_id)
|
||||
return course['lessons'] if course else None
|
||||
assert course_id in self.db, f"Course ID {course_id} does not exist."
|
||||
self.db.remove(course_id)
|
||||
|
||||
def get_all_courses(self):
|
||||
"""获取所有课程。"""
|
||||
return self.db.all()
|
||||
return list(self.db)
|
||||
|
||||
def to_json(self):
|
||||
return json.dumps(self.db)
|
||||
|
||||
# # 课程数据结构示例
|
||||
# course_data = {
|
||||
# 'course_id': 'CS101',
|
||||
# 'course_name': 'Computer Science 101',
|
||||
# 'course_img_path': 'images/cs101.png',
|
||||
# 'lessons': [
|
||||
# {
|
||||
# 'lesson_id': 'L001',
|
||||
# 'lesson_name': 'Introduction to Computer Science',
|
||||
# 'markdown': 'This is the introduction lesson.',
|
||||
# 'markdown_prompt': 'What is Computer Science?',
|
||||
# 'score_prompt': 'Please provide an overview of CS.'
|
||||
# },
|
||||
# {
|
||||
# 'lesson_id': 'L002',
|
||||
# 'lesson_name': 'Data Structures',
|
||||
# 'markdown': 'In this lesson, we cover Data Structures.',
|
||||
# 'markdown_prompt': 'What is an array?',
|
||||
# 'score_prompt': 'Explain how linked lists work.'
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
|
||||
# lesson_data = {
|
||||
# 'lesson_id': 'L003',
|
||||
# 'lesson_name': 'Algorithms',
|
||||
# 'markdown': 'In this lesson, we will discuss algorithms.',
|
||||
# 'markdown_prompt': 'What is a sorting algorithm?',
|
||||
# 'score_prompt': 'Explain the difference between merge sort and quicksort.'
|
||||
# }
|
||||
|
||||
# # 创建 CourseList 实例
|
||||
# course_list = CourseList()
|
||||
|
||||
# # 添加课程
|
||||
# course_list.add_course(course_data)
|
||||
|
||||
# # 添加课时到现有课程
|
||||
# course_list.add_lesson_to_course('CS101', lesson_data)
|
||||
|
||||
# # 获取并显示所有课程
|
||||
# courses = course_list.get_all_courses()
|
||||
# print(courses)
|
||||
|
||||
# # 获取某个课程的课时
|
||||
# lessons = course_list.get_lessons_of_course('CS101')
|
||||
# print(lessons)
|
||||
|
||||
# # 更新课程信息
|
||||
# updated_data = {'course_name': 'Computer Science 101 - Updated'}
|
||||
# course_list.update_course('CS101', updated_data)
|
||||
|
||||
# # 删除课程
|
||||
# course_list.delete_course('CS101')
|
||||
def items(self):
|
||||
assert type(self.db) is dict, "db is not a dict"
|
||||
return self.db.items()
|
||||
25
Html/db/data/course/CS101.json
Normal file
25
Html/db/data/course/CS101.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"course_id": "CS101",
|
||||
"course_name": "Computer Science 101",
|
||||
"course_auther": "John Doe",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"description":"这个老师很懒,没有写介绍",
|
||||
"lessons": [
|
||||
{
|
||||
"lesson_id": "L001",
|
||||
"lesson_name": "Introduction to Computer Science",
|
||||
"markdown": "This is the introduction lesson.",
|
||||
"markdown_prompt": "What is Computer Science?",
|
||||
"score_prompt": "Please provide an overview of CS.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
},
|
||||
{
|
||||
"lesson_id": "L002",
|
||||
"lesson_name": "Data Structures",
|
||||
"markdown": "In this lesson, we cover Data Structures.",
|
||||
"markdown_prompt": "What is an array?",
|
||||
"score_prompt": "Explain how linked lists work.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
25
Html/db/data/course/algorithm.json
Normal file
25
Html/db/data/course/algorithm.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"course_id": "algorithm",
|
||||
"course_name": "algorithm",
|
||||
"course_auther": "Chao Peng",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"description":"这个老师很懒,没有写介绍",
|
||||
"lessons": [
|
||||
{
|
||||
"lesson_id": "binary_search",
|
||||
"lesson_name": "Introduction to Algorithm",
|
||||
"markdown": "# 二分查找与二分答案\n\n## 二分查找\n\n### 引入\n\n二分是一个很简单基础,但很重要的知识点,为以后许多高级的数据结构与算法铺垫。\n\n下面是一个用二分的简单场景:\n\n假设小明从0到1000之间选择了一个数字但不告诉你,你可以不断猜测这个数,每次猜测小明会告知你的猜测得过大还是过小,问最多几次就一定能猜中?\n\n答案是利用二分查找的原理,猜测11次即可。\n\n1. 对于0到1000的答案备选区,猜测中位数500,假设过小,\n2. 则对于501到1000的答案备选区,猜测750,假设过大\n3. 则对于501到749的答案备选区,猜测625,假设过小,\n4. 则对于626到749区间......\n5. (688-749)\n6. (718-749)\n7. (734-749)\n8. (742-749)\n9. (746-749)\n10. (748-749)\n11. (749-749)\n\n在最差的情况下,第11次的答案备选区就一定长度为1了,也就是必然是答案。\n\n因此如果序列是有序的,就可以通过二分查找快速定位所需要的数据。\n\n#### 思考题(询问Agent以学习计算方法,或验证你的答案)\n\n对于上面那个题目,如果问题区间是1到4000,最差情况下需要猜测几次?\n\n### 练习:二分查找\n\n试试对于下面的题目,用代码实现一下二分查找。\n\n#### 题目:有序数组寻址\n\n给出一个长度为n的有序数组(从小到大),有q次询问,对于每次询问,输出指定数在数组中的下标。如果不存在则输出-1。\n\n##### 输入\n\n第一行一个整数n。(1<=n<=10^5)\n\n第二行n个用空格分开的整数ai。(0<=ai<=10^8)\n\n第三行一个整数q,表示询问的次数。(1<=q<=10^4)\n\n后q行,每行一个整数b,表示询问的数。(0<=b<=10^8)\n\n##### 输出\n\nq行,每行一个整数,对应每次询问的返回结果。\n\n##### 提示:\n\n完成代码后,通知Agent进行评测。\n\n如果你还不完全会这个算法,询问Agent获取提示并进行学习。\n",
|
||||
"markdown_prompt": "What is Algorithm?",
|
||||
"score_prompt": "Please provide an overview of CS.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
},
|
||||
{
|
||||
"lesson_id": "L002",
|
||||
"lesson_name": "Data Structures",
|
||||
"markdown": "### This is the introduction lesson.\n ### This is the introduction lesson.\n",
|
||||
"markdown_prompt": "What is an array?",
|
||||
"score_prompt": "Explain how linked lists work.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,21 +1,25 @@
|
||||
{
|
||||
"course_id": "CS101",
|
||||
"course_name": "Computer Science 101",
|
||||
"course_img_path": "images/cs101.png",
|
||||
"lessons": [
|
||||
{
|
||||
"lesson_id": "L001",
|
||||
"lesson_name": "Introduction to Computer Science",
|
||||
"markdown": "This is the introduction lesson.",
|
||||
"markdown_prompt": "What is Computer Science?",
|
||||
"score_prompt": "Please provide an overview of CS."
|
||||
},
|
||||
{
|
||||
"lesson_id": "L002",
|
||||
"lesson_name": "Data Structures",
|
||||
"markdown": "In this lesson, we cover Data Structures.",
|
||||
"markdown_prompt": "What is an array?",
|
||||
"score_prompt": "Explain how linked lists work."
|
||||
}
|
||||
]
|
||||
"CS101":{
|
||||
"course_id": "CS101",
|
||||
"course_name": "Computer Science 101",
|
||||
"course_description":"这个老师很懒,没有写介绍",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"course_create_date": "2023-01-01",
|
||||
"course_update_data": "2023-01-01"},
|
||||
|
||||
"algorithm":{
|
||||
"course_id": "algorithm",
|
||||
"course_name": "算法分析与设计",
|
||||
"course_description":"这个老师很懒,没有写介绍",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"course_create_date": "2023-01-01",
|
||||
"course_update_data": "2023-01-01"},
|
||||
|
||||
"data-structure":{
|
||||
"course_id": "data-structure",
|
||||
"course_name": "数据结构",
|
||||
"course_description":"这个老师很懒,没有写介绍",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"course_create_date": "2023-01-01",
|
||||
"course_update_data": "2023-01-01"}
|
||||
}
|
||||
25
Html/db/data/course/data-structure.json
Normal file
25
Html/db/data/course/data-structure.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"course_id": "data-structure",
|
||||
"course_name": "data-structure",
|
||||
"course_auther": "Chao Peng",
|
||||
"course_img_path": "/static/image/algorithm/book_cover.png",
|
||||
"description":"这个老师很懒,没有写介绍",
|
||||
"lessons": [
|
||||
{
|
||||
"lesson_id": "L001",
|
||||
"lesson_name": "Introduction to Data structure",
|
||||
"markdown": "This is the introduction lesson.",
|
||||
"markdown_prompt": "What is Data structure?",
|
||||
"score_prompt": "Please provide an overview of CS.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
},
|
||||
{
|
||||
"lesson_id": "L002",
|
||||
"lesson_name": "Data Structures",
|
||||
"markdown": "In this lesson, we cover Data Structures.",
|
||||
"markdown_prompt": "What is an array?",
|
||||
"score_prompt": "Explain how linked lists work.",
|
||||
"lesson_img_path": "/static/image/algorithm/book_cover.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
40
Html/db/data/user/a.json
Normal file
40
Html/db/data/user/a.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"user_id": "a",
|
||||
"select_course": [
|
||||
"algorithm",
|
||||
"data-structure"
|
||||
],
|
||||
"head_icon": "",
|
||||
"course_process_dict": {
|
||||
"algorithm": {
|
||||
"lesson_processs": [
|
||||
[
|
||||
[],
|
||||
"L001"
|
||||
],
|
||||
[
|
||||
[],
|
||||
"L002"
|
||||
]
|
||||
],
|
||||
"course_put_in_date": "",
|
||||
"course_last_study_date": "",
|
||||
"course_total_study_time": 0
|
||||
},
|
||||
"data-structure": {
|
||||
"lesson_processs": [
|
||||
[
|
||||
[],
|
||||
"L001"
|
||||
],
|
||||
[
|
||||
[],
|
||||
"L002"
|
||||
]
|
||||
],
|
||||
"course_put_in_date": "",
|
||||
"course_last_study_date": "",
|
||||
"course_total_study_time": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,105 @@
|
||||
{
|
||||
"user_id": "user123",
|
||||
"select_course": ["algorithm", "data-structure"],
|
||||
"head_icon": "/static/image/book_cover.jpg",
|
||||
"course_process_dict": {
|
||||
"algorithm": {
|
||||
"course_process": {
|
||||
"user_id": "cake",
|
||||
"select_course": [
|
||||
"CS101",
|
||||
"algorithm",
|
||||
"data-structure"
|
||||
],
|
||||
"head_icon": "/static/image/book_cover.jpg",
|
||||
"course_process_dict": {
|
||||
"algorithm": {
|
||||
"lesson_processs": [
|
||||
{
|
||||
"lesson_process": [
|
||||
[
|
||||
[
|
||||
{
|
||||
"chapter_info": {
|
||||
"dialog": ["This is chapter 1 dialog"],
|
||||
"score": 85,
|
||||
"is_rebuttal": true,
|
||||
"rebuttal_score": 90
|
||||
}
|
||||
},
|
||||
{
|
||||
"chapter_info": {
|
||||
"dialog": ["This is chapter 2 dialog"],
|
||||
"score": 75,
|
||||
"is_rebuttal": false,
|
||||
"rebuttal_score": 0
|
||||
}
|
||||
"title": "\u5f15\u5165",
|
||||
"dialog": [
|
||||
{
|
||||
"id": "0b26417b9a4a41c3a86a63e96ac279f7",
|
||||
"timestamp": "2025-01-01 01:40:36",
|
||||
"name": "system",
|
||||
"content": "You're a helpful assistant.\n\n## \u4f60\u7684\u89d2\u8272\uff1a\n\u4f60\u9700\u8981\u5e2e\u52a9\u5b66\u751f\u5b66\u4e60\u7b97\u6cd5\uff0c\u5b8c\u6210\u7279\u5b9a\u7684\u7f16\u7a0b\u4efb\u52a1\u3002\n\n## \u4f60\u9700\u8981\u505a\u7684\uff1a\n0. \u4f60\u5fc5\u987b\u6839\u636e\u8001\u5e08\u63d0\u4f9b\u7684\u6559\u5b66\u5927\u7eb2\uff0c\u6309\u7167\u7ae0\u8282\u987a\u5e8f\uff0c\u4f9d\u6b21\u5b66\u4e60\u3002\n1. \u5b66\u751f\u53ef\u80fd\u4f1a\u63d0\u51fa\u4e00\u4e9b\u95ee\u9898\uff0c\u4f60\u65e0\u9700\u56de\u7b54\u95ee\u9898\uff0c\u800c\u662f\u6839\u636e\u4e0a\u4e0b\u6587\uff08\u6bd4\u5982\u5b66\u751f\u81ea\u5df1\u7684\u4ee3\u7801\uff09\u6765\u5206\u6790\uff0c\u5e76\u7ed9\u51fa\u4e00\u6b65\u7684\u89e3\u51b3\u65b9\u6848\u3002\n2. \u6559\u5b66\u5927\u7eb2\u4e2d\u4f1a\u6307\u660e\u6bcf\u4e2a\u7ae0\u8282\u7684\u5b66\u4e60\u76ee\u6807\uff0c\u4f60\u6309\u7167\u76ee\u6807\u5b66\u4e60\u3002\n3. \u7cfb\u7edf\u4f1aoccasionally gather\u5b66\u751f\u4fe1\u606f\uff0c\u4f60\u9700\u8981\u5206\u6790\u5b66\u751f\u5b66\u4e60\u8bb0\u5f55\uff0c\u8c03\u7528\u5fc5\u8981\u7684\u51fd\u6570\u3002\n\n## \u6ce8\u610f\u4e8b\u9879\uff1a\n1. \u786e\u4fdd\u4f7f\u7528\u5de5\u5177\u51fd\u6570\u65f6\uff0c\u63d0\u4f9b\u7684\u53c2\u6570\u7c7b\u578b\u548c\u503c\u662f\u6b63\u786e\u7684\u3002\n2. \u4e0d\u8981\u592a\u76f8\u4fe1\u81ea\u5df1\uff0c\u4f8b\u5982\uff0c\u5f53\u524d\u4f4d\u7f6e\uff0c\u5f53\u524d\u65f6\u95f4\u7b49\uff0c\u4f60\u53ef\u4ee5\u5c1d\u8bd5\u4f7f\u7528\u5de5\u5177\u51fd\u6570\u83b7\u53d6\u4fe1\u606f\u3002\n3. \u5982\u679c\u51fd\u6570\u6267\u884c\u5931\u8d25\uff0c\u4f60\u9700\u8981\u5206\u6790\u9519\u8bef\u5e76\u5c1d\u8bd5\u89e3\u51b3\u3002\n4. \u786e\u4fdd\u5b66\u751f\u63d0\u51fa\u7684\u95ee\u9898\u6216\u60f3\u6cd5\u662f\u5426\u4e0e\u5f53\u524d\u7ae0\u8282\u76f8\u5173\uff0c\u5982\u679c\u4e0d\u76f8\u5173\uff0c\u4f60\u5e94\u7b54\u5e76\u63d0\u9192\u5b66\u751f\u5173\u6ce8\u5f53\u524d\u7ae0\u8282\u3002\n\n## \u8d44\u6e90\uff1a\n1. \u4f60\u53ef\u4ee5\u4f7f\u7528\u7684\u5de5\u5177\u51fd\u6570\u3002\n2. \u4e0a\u4e0b\u6587\uff0c\u5305\u62ec\u5b66\u751f\u7684\u4ee3\u7801\uff0c\u548c\u6559\u5b66\u5927\u7eb2\u3002\n",
|
||||
"role": "system",
|
||||
"url": null,
|
||||
"metadata": null
|
||||
},
|
||||
{
|
||||
"id": "461938c9265547c9bd0187ece94d659d",
|
||||
"timestamp": "2025-01-01 01:40:43",
|
||||
"name": "system",
|
||||
"content": "##The Chapter Chain##\n(Your Now Chapter) Chapter 1: \n\u4e8c\u5206\u662f\u4e00\u4e2a\u5f88\u7b80\u5355\u57fa\u7840\uff0c\u4f46\u5f88\u91cd\u8981\u7684\u77e5\u8bc6\u70b9\uff0c\u4e3a\u4ee5\u540e\u8bb8\u591a\u9ad8\u7ea7\u7684\u6570\u636e\u7ed3\u6784\u4e0e\u7b97\u6cd5\u94fa\u57ab\u3002\n\n\u4e0b\u9762\u662f\u4e00\u4e2a\u7528\u4e8c\u5206\u7684\u7b80\u5355\u573a\u666f\uff1a\n\n\u5047\u8bbe\u5c0f\u660e\u4ece0\u52301000\u4e4b\u95f4\u9009\u62e9\u4e86\u4e00\u4e2a\u6570\u5b57\u4f46\u4e0d\u544a\u8bc9\u4f60\uff0c\u4f60\u53ef\u4ee5\u4e0d\u65ad\u731c\u6d4b\u8fd9\u4e2a\u6570\uff0c\u6bcf\u6b21\u731c\u6d4b\u5c0f\u660e\u4f1a\u544a\u77e5\u4f60\u7684\u731c\u6d4b\u5f97\u8fc7\u5927\u8fd8\u662f\u8fc7\u5c0f\uff0c\u95ee\u6700\u591a\u51e0\u6b21\u5c31\u4e00\u5b9a\u80fd\u731c\u4e2d\uff1f\n\n\u7b54\u6848\u662f\u5229\u7528\u4e8c\u5206\u67e5\u627e\u7684\u539f\u7406\uff0c\u731c\u6d4b11\u6b21\u5373\u53ef\u3002\n\n1. \u5bf9\u4e8e0\u52301000\u7684\u7b54\u6848\u5907\u9009\u533a\uff0c\u731c\u6d4b\u4e2d\u4f4d\u6570500\uff0c\u5047\u8bbe\u8fc7\u5c0f\uff0c\n2. \u5219\u5bf9\u4e8e501\u52301000\u7684\u7b54\u6848\u5907\u9009\u533a\uff0c\u731c\u6d4b750\uff0c\u5047\u8bbe\u8fc7\u5927\n3. \u5219\u5bf9\u4e8e501\u5230749\u7684\u7b54\u6848\u5907\u9009\u533a\uff0c\u731c\u6d4b625\uff0c\u5047\u8bbe\u8fc7\u5c0f\uff0c\n4. \u5219\u5bf9\u4e8e626\u5230749\u533a\u95f4......\n5. \uff08688-749\uff09\n6. \uff08718-749\uff09\n7. \uff08734-749\uff09\n8. \uff08742-749\uff09\n9. \uff08746-749\uff09\n10. \uff08748-749\uff09\n11. \uff08749-749\uff09\n\n\u5728\u6700\u5dee\u7684\u60c5\u51b5\u4e0b\uff0c\u7b2c11\u6b21\u7684\u7b54\u6848\u5907\u9009\u533a\u5c31\u4e00\u5b9a\u957f\u5ea6\u4e3a1\u4e86\uff0c\u4e5f\u5c31\u662f\u5fc5\u7136\u662f\u7b54\u6848\u3002\n\n\u56e0\u6b64\u5982\u679c\u5e8f\u5217\u662f\u6709\u5e8f\u7684\uff0c\u5c31\u53ef\u4ee5\u901a\u8fc7\u4e8c\u5206\u67e5\u627e\u5feb\u901f\u5b9a\u4f4d\u6240\u9700\u8981\u7684\u6570\u636e\u3002\n\n#### \u601d\u8003\u9898\uff08\u8be2\u95eeAgent\u4ee5\u5b66\u4e60\u8ba1\u7b97\u65b9\u6cd5\uff0c\u6216\u9a8c\u8bc1\u4f60\u7684\u7b54\u6848\uff09\n\n\u5bf9\u4e8e\u4e0a\u9762\u90a3\u4e2a\u9898\u76ee\uff0c\u5982\u679c\u95ee\u9898\u533a\u95f4\u662f1\u52304000\uff0c\u6700\u5dee\u60c5\u51b5\u4e0b\u9700\u8981\u731c\u6d4b\u51e0\u6b21\uff1f\n\n\nHere are some concrete instructions:\n\n\u672c\u5c0f\u8282\u8fdb\u884c\u4e8c\u5206\u67e5\u627e\u7684\u5f15\u5165\uff0c\u9996\u5148\u5e2e\u52a9\u5b66\u751f\u7406\u89e3\u6559\u6848\u5f15\u5165\u7ae0\u8282\u7684\u6545\u4e8b\u3002\n\n\u786e\u4fdd\u5b66\u751f\u7406\u89e3\u4e86\u5f15\u5165\u540e\uff0c\u5728\u8fdb\u884c\u601d\u8003\u9898\u3002\n\n\u5982\u679c\u4e0d\u8fdb\u884c\u601d\u8003\u9898\uff0c\u5219\u8be2\u95ee\u4e00\u4e0b\u662f\u5426\u4e0d\u8fdb\u884c\u601d\u8003\u9898\uff0c\u786e\u8ba4\u540e\u8fdb\u5165\u4e0b\u4e00\u8282\u3002\n\n\u5982\u679c\u8fdb\u884c\u601d\u8003\u9898\uff0c\u544a\u77e5\u5b66\u751f\u8ba1\u7b97\u65b9\u6cd5\u5e76\u9a8c\u8bc1\u7b54\u6848\uff08\u7b54\u6848\u662f13\u6b21\uff09\n\n\u8ba1\u7b97\u65b9\u6cd5\uff1a\n\n4000\u662f\u521d\u59cb\u7b54\u6848\u533a\u95f4\u957f\u5ea6\uff0c\u6bcf\u6b21\u8be2\u95ee\u80fd\u591f\u6392\u9664\u4e00\u534a\u7684\u533a\u95f4\uff0c\u5f53\u533a\u95f4\u957f\u5ea6\u5c0f\u4e8e\u7b49\u4e8e1\u65f6\uff0c\u518d\u8fdb\u884c\u4e00\u6b21\u731c\u6d4b\u5c31\u4e00\u5b9a\u662f\u7b54\u6848\u3002\n\n4000\u4e0d\u65ad\u9664\u4ee52\uff0c\u966412\u6b21\u5c31\u5c0f\u4e8e\u7b49\u4e8e1\u4e86\uff0c\u518d\u52a0\u4e00\u6b21\u5c31\u4e00\u5b9a\u662f\u7b54\u6848\u3002\u6700\u540e\u662f12+1=13\u6b21\u3002\n\n\uff08\u6bd44000\u5927\u7684\u6700\u5c0f2\u7684\u6b21\u65b9\u6570\uff0c4096\u5c31\u662f2\u768412\u6b21\u65b9\uff0c\u8fd9\u91cc\u768412\u5c31\u662f\u7b54\u6848\u4e2d\u768412\uff0c\u6216\u8005\u5199\u4f5c\"\u4e0a\u53d6\u6574(log2(4000))\")\n\n\u8be2\u95ee\u5b66\u751f\uff0c\u5f53\u5b66\u751f\u544a\u77e5\u7406\u89e3\u540e\uff0c\u8fdb\u5165\u4e0b\u4e00\u8282\u3002\n\n\n\n\n",
|
||||
"role": "system",
|
||||
"url": null,
|
||||
"metadata": null
|
||||
},
|
||||
{
|
||||
"id": "4d63161cb43344d79a2a27abde4a4439",
|
||||
"timestamp": "2025-01-01 01:40:43",
|
||||
"name": "user",
|
||||
"content": "\u7b54\u6848\u662f13\uff0clog2 4000+1",
|
||||
"role": "user",
|
||||
"url": null,
|
||||
"metadata": null
|
||||
},
|
||||
{
|
||||
"id": "af2e4a0d68f34e61b977ee54f72acf63",
|
||||
"timestamp": "2025-01-01 01:40:46",
|
||||
"name": "user_342ee332-16c3-4722-a7aa-fd020088aba1",
|
||||
"content": {
|
||||
"thought": "\u5b66\u751f\u7406\u89e3\u4e86\u601d\u8003\u9898\u7684\u7b54\u6848\uff0c\u4e0b\u4e00\u6b65\u8fdb\u5165\u4e0b\u4e00\u8282\u3002",
|
||||
"speak": "\u597d\u7684\uff0c\u4f60\u7684\u8ba1\u7b97\u65b9\u6cd5\u662f\u6b63\u786e\u7684\uff0c\u6700\u5dee\u60c5\u51b5\u4e0b\u9700\u8981\u731c\u6d4b13\u6b21\u3002\u6211\u4eec\u73b0\u5728\u53ef\u4ee5\u8fdb\u5165\u4e0b\u4e00\u8282\u3002",
|
||||
"function": "[{\"name\": \"next_chapter\", \"arguments\": {}}]"
|
||||
},
|
||||
"role": "assistant",
|
||||
"url": null,
|
||||
"metadata": null
|
||||
}
|
||||
],
|
||||
"score": 10,
|
||||
"is_rebuttal": false,
|
||||
"rebuttal_score": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"binary_search"
|
||||
],
|
||||
[
|
||||
[],
|
||||
"L002"
|
||||
]
|
||||
],
|
||||
"course_put_in_date": "2024-01-01",
|
||||
"course_last_study_date": "2024-12-25",
|
||||
"course_total_study_time": 120
|
||||
}
|
||||
},
|
||||
"data-structure": {
|
||||
"course_process": {
|
||||
"course_put_in_date": "",
|
||||
"course_last_study_date": "2025-01-01",
|
||||
"course_total_study_time": 0
|
||||
},
|
||||
"data-structure": {
|
||||
"lesson_processs": [
|
||||
{
|
||||
"lesson_process": [
|
||||
{
|
||||
"chapter_info": {
|
||||
"dialog": ["This is course2 chapter 1 dialog"],
|
||||
"score": 88,
|
||||
"is_rebuttal": false,
|
||||
"rebuttal_score": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
[
|
||||
[],
|
||||
"L001"
|
||||
],
|
||||
[
|
||||
[],
|
||||
"L002"
|
||||
]
|
||||
],
|
||||
"course_put_in_date": "2024-01-01",
|
||||
"course_last_study_date": "2024-12-25",
|
||||
"course_total_study_time": 90
|
||||
"course_put_in_date": "",
|
||||
"course_last_study_date": "",
|
||||
"course_total_study_time": 0
|
||||
},
|
||||
"CS101": {
|
||||
"lesson_processs": [
|
||||
[
|
||||
[],
|
||||
"L001"
|
||||
],
|
||||
[
|
||||
[],
|
||||
"L002"
|
||||
]
|
||||
],
|
||||
"course_put_in_date": "",
|
||||
"course_last_study_date": "",
|
||||
"course_total_study_time": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
"user123": "password123",
|
||||
"user456": "password456",
|
||||
"user789": "password789",
|
||||
"cake": "12138ckC"
|
||||
"cake": "123123",
|
||||
"a": "123123"
|
||||
}
|
||||
|
||||
204
Html/db/user.py
204
Html/db/user.py
@@ -1,116 +1,116 @@
|
||||
from datetime import date
|
||||
from tinydb import TinyDB, Query
|
||||
import os
|
||||
# Example usage:
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
LOCAL_USER_DATA_DIR = "data/user/" # only use locally, not for other .py files
|
||||
|
||||
class User:
|
||||
def __init__(self, db_file='user_data.json'):
|
||||
"""初始化用户管理,自动打开并加载 JSON 数据文件。"""
|
||||
self.db_file = db_file
|
||||
self.db = TinyDB(self.db_file)
|
||||
self.user_query = Query()
|
||||
def __init__(self, user_id, select_course, head_icon, course_process_dict, save_path):
|
||||
self.user_id = user_id # User ID
|
||||
self.select_course = select_course # List of selected courses
|
||||
self.head_icon = head_icon # URL of the user's head icon
|
||||
self.course_process_dict = course_process_dict # Dictionary of courses with their progress
|
||||
self.save_path = save_path
|
||||
|
||||
def add_user(self, user_data):
|
||||
"""添加新的用户"""
|
||||
if not self.db.search(self.user_query.user_id == user_data['user_id']):
|
||||
self.db.insert(user_data)
|
||||
else:
|
||||
print(f"User with ID {user_data['user_id']} already exists.")
|
||||
def save_chapter_memory(self, course_id, lesson_id, subchapter_title, mem_list, score, is_rebuttal):
|
||||
'''
|
||||
Save the memory of a chapter
|
||||
'''
|
||||
try:
|
||||
if(course_id not in self.course_process_dict):
|
||||
self.course_process_dict[course_id] = {'lesson_processs':[], 'course_put_in_date':'', 'course_last_study_date':'', 'course_total_study_time':0}
|
||||
self.course_process_dict[course_id]['course_last_study_date'] = datetime.now().strftime('%Y-%m-%d')
|
||||
for _ in range(len(self.course_process_dict[course_id]['lesson_processs'])):
|
||||
lesson_process, lid = self.course_process_dict[course_id]['lesson_processs'][_]
|
||||
if lid == lesson_id:
|
||||
saveed = False
|
||||
for i in range(len(lesson_process)):
|
||||
chapter_info = lesson_process[i]
|
||||
if chapter_info['title'] == subchapter_title:
|
||||
chapter_info['dialog'] = mem_list
|
||||
if is_rebuttal:
|
||||
chapter_info['rebuttal_score'] = score
|
||||
else:
|
||||
chapter_info['score'] = score
|
||||
chapter_info['is_rebuttal'] = is_rebuttal
|
||||
saveed = True
|
||||
break
|
||||
if not saveed:
|
||||
lesson_process.append({
|
||||
'title': subchapter_title,
|
||||
'dialog': mem_list,
|
||||
'score': score,
|
||||
'is_rebuttal': is_rebuttal,
|
||||
'rebuttal_score': score if is_rebuttal else 0,
|
||||
})
|
||||
break
|
||||
self.save_to_file()
|
||||
except Exception as e:
|
||||
print("=-=-=-=-=-=")
|
||||
print(e)
|
||||
def get_course_progress(self):
|
||||
for course_name, course_data in self.course_process_dict.items():
|
||||
print(f"Course: {course_name}")
|
||||
for lessons,lesson_id in course_data["lesson_processs"]:
|
||||
print(f" Lesson ID: {lesson_id}")
|
||||
for chapter in lessons:
|
||||
chapter_info = chapter
|
||||
print(f" Chapter Dialog: {chapter_info['dialog']}")
|
||||
print(f" Chapter Score: {chapter_info['score']}")
|
||||
print(f" Rebuttal: {'Yes' if chapter_info['is_rebuttal'] else 'No'}")
|
||||
if chapter_info['is_rebuttal']:
|
||||
print(f" Rebuttal Score: {chapter_info['rebuttal_score']}")
|
||||
|
||||
def get_user(self, user_id):
|
||||
"""根据 user_id 获取用户信息"""
|
||||
result = self.db.search(self.user_query.user_id == user_id)
|
||||
return result[0] if result else None
|
||||
def select_new_course(self, course_id, course):
|
||||
self.select_course.append(course_id)
|
||||
|
||||
def update_user(self, user_id, updated_data):
|
||||
"""更新用户信息"""
|
||||
self.db.update(updated_data, self.user_query.user_id == user_id)
|
||||
|
||||
def delete_user(self, user_id):
|
||||
"""删除用户"""
|
||||
self.db.remove(self.user_query.user_id == user_id)
|
||||
|
||||
def get_all_users(self):
|
||||
"""获取所有用户"""
|
||||
return self.db.all()
|
||||
self.course_process_dict[course_id] = {'lesson_processs':[], 'course_put_in_date':'', 'course_last_study_date':'','course_total_study_time':0}
|
||||
self.course_process_dict[course_id]['lesson_processs']
|
||||
for lesson in course.lessons:
|
||||
self.course_process_dict[course_id]['lesson_processs'].append(([], lesson['lesson_id']))
|
||||
|
||||
|
||||
# 用户数据结构示例
|
||||
# user_data = {
|
||||
# 'user_id': 'user123',
|
||||
# 'select_course': ['course1', 'course2'],
|
||||
# 'course_process_dict': {
|
||||
# 'course1': {
|
||||
# 'course_process': {
|
||||
# 'lesson_processs': [
|
||||
# {
|
||||
# 'lesson_process': [
|
||||
# {
|
||||
# 'chapter_info': {
|
||||
# 'dialog': ['This is chapter 1 dialog'],
|
||||
# 'score': 85,
|
||||
# 'is_rebuttal': True,
|
||||
# 'rebuttal_score': 90
|
||||
# }
|
||||
# },
|
||||
# {
|
||||
# 'chapter_info': {
|
||||
# 'dialog': ['This is chapter 2 dialog'],
|
||||
# 'score': 75,
|
||||
# 'is_rebuttal': False,
|
||||
# 'rebuttal_score': 0
|
||||
# }
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# ],
|
||||
# 'course_put_in_date': date(2024, 1, 1),
|
||||
# 'course_last_study_date': date(2024, 12, 25),
|
||||
# 'course_total_study_time': 120 # 总学习时间:分钟
|
||||
# }
|
||||
# },
|
||||
# 'course2': {
|
||||
# 'course_process': {
|
||||
# 'lesson_processs': [
|
||||
# {
|
||||
# 'lesson_process': [
|
||||
# {
|
||||
# 'chapter_info': {
|
||||
# 'dialog': ['This is course2 chapter 1 dialog'],
|
||||
# 'score': 88,
|
||||
# 'is_rebuttal': False,
|
||||
# 'rebuttal_score': 0
|
||||
# }
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# ],
|
||||
# 'course_put_in_date': date(2024, 2, 1),
|
||||
# 'course_last_study_date': date(2024, 12, 24),
|
||||
# 'course_total_study_time': 90
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
with open(self.save_path, 'w') as f:
|
||||
json.dump(self.__json__(), f, indent=4)
|
||||
|
||||
# updated_user_data = {
|
||||
# 'select_course': ['course1', 'course3']
|
||||
# }
|
||||
def save_to_file(self):
|
||||
print(f"saved at {self.save_path}")
|
||||
self.get_course_progress()
|
||||
with open(self.save_path, 'w') as f:
|
||||
json.dump(self.__json__(), f, indent=4)
|
||||
|
||||
# # 创建 User 实例
|
||||
# user_list = User()
|
||||
def __json__(self):
|
||||
return {
|
||||
'user_id': self.user_id,
|
||||
'select_course': self.select_course,
|
||||
'head_icon': self.head_icon,
|
||||
'course_process_dict': self.course_process_dict
|
||||
}
|
||||
|
||||
# # 添加用户
|
||||
# user_list.add_user(user_data)
|
||||
def to_json(self):
|
||||
return json.dumps(self.__json__(), indent=4)
|
||||
|
||||
# # 获取用户信息
|
||||
# user = user_list.get_user('user123')
|
||||
# print(user)
|
||||
def load_user_from_json(user_id, user_data_dir = None)-> User:
|
||||
USER_DATA_DIR = user_data_dir if user_data_dir else LOCAL_USER_DATA_DIR
|
||||
with open(os.path.join(USER_DATA_DIR, f'{user_id}.json'), "r") as f:
|
||||
raw_json = f.read()
|
||||
user_data = json.loads(raw_json)
|
||||
return User(save_path = os.path.join(USER_DATA_DIR, f'{user_id}.json'), **user_data)
|
||||
|
||||
# # 更新用户选择的课程
|
||||
# user_list.update_user('user123', updated_user_data)
|
||||
def create_user_json(user_id, user_data_dir = None):
|
||||
USER_DATA_DIR = user_data_dir if user_data_dir else LOCAL_USER_DATA_DIR
|
||||
with open(os.path.join(USER_DATA_DIR, f'{user_id}.json'), "w") as f:
|
||||
f.write(json.dumps({
|
||||
'user_id': user_id,
|
||||
'select_course': [],
|
||||
'head_icon': '',
|
||||
'course_process_dict': {}
|
||||
}))
|
||||
|
||||
# # 获取所有用户
|
||||
# all_users = user_list.get_all_users()
|
||||
# print(all_users)
|
||||
if(__name__ == "__main__"):
|
||||
|
||||
# # 删除用户
|
||||
# user_list.delete_user('user123')
|
||||
user = load_user_from_json('cake')
|
||||
|
||||
|
||||
user.get_course_progress()
|
||||
|
||||
@@ -1,36 +1,48 @@
|
||||
from tinydb import TinyDB, Query
|
||||
import json
|
||||
|
||||
class UserList:
|
||||
def __init__(self, db_file='db/data/user/user_id_list.json'):
|
||||
"""初始化用户管理,自动打开并加载 JSON 数据文件。"""
|
||||
self.db_file = db_file
|
||||
self.db = TinyDB(self.db_file)
|
||||
self.user_query = Query()
|
||||
with open(self.db_file, 'r') as f:
|
||||
self.db = json.load(f)
|
||||
|
||||
def add_user(self, user_id, password):
|
||||
"""添加新的用户登录信息"""
|
||||
# 检查是否已经有该用户
|
||||
if not self.db.search(self.user_query.user_id == user_id):
|
||||
self.db.insert({'user_id': user_id, 'password': password})
|
||||
if user_id not in self.db:
|
||||
self.db[user_id] = password
|
||||
with open(self.db_file, 'w') as f:
|
||||
json.dump(self.db, f, indent=4)
|
||||
else:
|
||||
print(f"User with ID {user_id} already exists.")
|
||||
|
||||
def get_user(self, user_id):
|
||||
def has_user(self, user_id):
|
||||
"""检查用户是否存在"""
|
||||
return user_id in self.db
|
||||
|
||||
def get_user_pswd(self, user_id):
|
||||
"""获取指定 user_id 的用户信息"""
|
||||
result = self.db.search(self.user_query.user_id == user_id)
|
||||
return result[0] if result else None
|
||||
if user_id in self.db:
|
||||
result = self.db[user_id]
|
||||
return result
|
||||
return None
|
||||
|
||||
def update_password(self, user_id, new_password):
|
||||
"""更新用户的密码"""
|
||||
self.db.update({'password': new_password}, self.user_query.user_id == user_id)
|
||||
assert self.db.get(user_id) is not None, f"User with ID {user_id} does not exist."
|
||||
self.db[user_id] = new_password
|
||||
with open(self.db_file, 'w') as f:
|
||||
json.dump(self.db, f, indent=4)
|
||||
|
||||
def delete_user(self, user_id):
|
||||
"""删除用户"""
|
||||
self.db.remove(self.user_query.user_id == user_id)
|
||||
assert self.db.get(user_id) is not None, f"User with ID {user_id} does not exist."
|
||||
self.db.remove(user_id)
|
||||
|
||||
def get_all_users(self):
|
||||
"""获取所有用户的信息"""
|
||||
return self.db.all()
|
||||
return list(self.db.keys())
|
||||
|
||||
# 创建 UserList 实例
|
||||
# user_list = UserList()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user