diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/.env.example b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/.env.example
new file mode 100644
index 00000000..8b888822
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/.env.example
@@ -0,0 +1,13 @@
+LLM_MODEL_ID=""
+LLM_API_KEY=""
+LLM_BASE_URL=""
+
+# 超时时间(可选,默认60秒)
+LLM_TIMEOUT=""
+
+# 服务器配置
+HOST=""
+PORT=""
+
+# CORS配置
+CORS_ORIGINS=""
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/README.md b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/README.md
new file mode 100644
index 00000000..85311b4b
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/README.md
@@ -0,0 +1,183 @@
+# FitnessPlannerAgent - 健身训练规划助手
+
+> 基于HelloAgents框架的健身规划助手
+
+## 📝 项目简介
+
+FitnessPlannerAgent是一个健身训练规划助手,能够根据用户基本信息自动规划每周期的健身计划。
+
+### 核心功能
+- ✅ 智能建议:基于LLM和用户提供的基本信息进行分析和规划训练。
+
+
+## 🛠️ 技术栈
+
+- HelloAgents框架(SimpleAgent)
+- QWEN API(智能分析)
+
+## 🚀 快速开始
+
+### 安装依赖
+
+```bash
+pip install -r requirements.txt
+```
+
+### 配置LLM参数
+
+**方式1: 使用.env文件(推荐)**
+
+```bash
+# 复制示例文件
+cp .env.example .env
+
+# 编辑.env文件,填入你的配置
+# LLM_MODEL_ID=Qwen/Qwen2.5-72B-Instruct
+# LLM_API_KEY=your_api_key_here
+# LLM_BASE_URL=https://api-inference.modelscope.cn/v1/
+```
+
+### 运行项目
+
+在终端进入当项目所在的EugeneChanQAQ-smart_fitness_planner目录激活虚拟环境。
+
+```bash
+venv_fit/Scripts/activate
+# 激活虚拟环境
+python -m uvicorn app.api.main:app --reload --host 0.0.0.0 --port 8000
+# 启动项目
+```
+
+## 📖 使用示例
+
+### 完整功能
+
+1. 用户输入自己的基本信息(身高、体重、年龄)
+2. 系统生成周期性的健身规划
+
+## 🎯 项目亮点
+
+- **智能化**:利用LLM根据个人身体基本数据,提供专业的健身训练建议
+- **可扩展**:易于添加新的工具
+
+## 📂 项目结构
+
+```
+EugeneChanQAQ-smart_fitness_planner/
+│
+├── app/ # 🍱 FastAPI 服务主体
+│ ├── config.py # 配置文件(应用名、版本、路径等)
+│ ├── api/ # FastAPI 相关
+│ │ ├── routers # 路由
+│ │ │ └──train.py # 路由
+│ │ ├── main.py # FastAPI 主入口
+│ ├── agents/ # 核心 Agent 逻辑模块
+│ │ ├── train_planner.py #
+│ │ ├── state_manager.py # 暂空
+│ │ ├── \_\_init__.py
+│ ├── models/ # Pydantic 请求模型
+│ │ └── schemas.py # 数据模型
+│ └── services/
+│ └── llm_service.py #
+│
+├── tests/
+│ └── test_agent.py # 暂空
+│
+├── requirements.txt # Python依赖
+└── README.md # 项目说明
+```
+
+## 🔧 技术实现
+
+
+### 智能体设计
+
+使用HelloAgents的SimpleAgent。
+
+## 📊 示例输出
+
+```markdown
+============================================================
+🚀 HelloAgents健身规划助手 v1.0.0
+============================================================
+应用名称: HelloAgents健身规划助手
+版本: 1.0.0
+服务器: 0.0.0.0:8000
+LLM API Key: 已配置
+LLM Base URL: https://dashscope.aliyuncs.com/compatible-mode/v1
+LLM Model: qwen-max
+日志级别: INFO
+
+ ✔验证通过
+
+============================================================
+📚 API文档: http://localhost:8000/docs
+📖 ReDoc文档: http://localhost:8000/redoc
+============================================================
+
+INFO: Application startup complete.
+INFO: 127.0.0.1:57008 - "GET / HTTP/1.1" 307 Temporary Redirect
+INFO: 127.0.0.1:57008 - "GET /train/ HTTP/1.1" 200 OK
+INFO: 127.0.0.1:57008 - "GET /favicon.ico HTTP/1.1" 404 Not Found
+
+============================================================
+📥 收到训练计划制定请求:
+ 身高: 183
+ 体重: 76
+ 年龄: 21
+============================================================
+
+获取Agent系统
+开始初始化智能体健身规划系统
+✅ LLM服务初始化成功
+ 提供商: qwen
+ 模型: qwen-max
+创建健身规划Agent
+
+============================================================
+🚀 开始智能体规划训练...
+身高:183
+体重:76
+年龄:21
+
+============================================================
+制定训练计划中...
+训练规划结果: [
+ {"day":1,"action":"深蹲","muscle":"腿部","group_num":3,"amount":12},
+ {"day":1,"action":"卧推","muscle":"胸部","group_num":3,"amount":10},
+ {"day":1,"action":"引体向上","muscle":"背部","group_num":3,"amount":8},
+ {"day":2,"action":"休息"},
+ {"day":3,"action":"硬拉","muscle":"背部","group_num":3,"amount":10},
+ ...
+
+============================================================
+✅ 训练计划生成完成!
+============================================================
+
+✅ 训练计划生成成功,准备返回响应
+
+INFO: 127.0.0.1:61389 - "POST /train/plan HTTP/1.1" 200 OK
+```
+
+## 🚧 未来改进
+
+- [ ] 提供更多的基础信息以及特殊需求填写(性别、健身目的等)
+- [ ] 添加食谱规划Agent(帮助提高健身效率)
+- [ ] 调用API查找附近的健身餐食
+- [ ] 提供周期性反馈,根据用户的最新数据更改健身策略和方案
+- [ ] 生成用户身体数据报告
+
+## 👤 作者
+
+- GitHub: [@EugeneChanQAQ](https://github.com/EugeneChanQAQ)
+- 项目链接:[FitnessPlannerAgent](https://github.com/datawhalechina/Hello-Agents/tree/main/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner)
+
+## 🙏 致谢
+
+感谢Datawhale社区和Hello-Agents项目!
+
+## 📄 许可证
+
+所有共创项目遵循CC BY-NC-SA 4.0 License,欢迎学习和共创。
+
+
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/__init__.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/__init__.py
new file mode 100644
index 00000000..2d66a7db
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/__init__.py
@@ -0,0 +1,4 @@
+__all__ = [
+ "train_planner.py",
+ "state_manager",
+]
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/state_manager.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/state_manager.py
new file mode 100644
index 00000000..e69de29b
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/train_planner.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/train_planner.py
new file mode 100644
index 00000000..b417836c
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/agents/train_planner.py
@@ -0,0 +1,185 @@
+import json
+from typing import Dict, Any, List
+from hello_agents import SimpleAgent
+
+from ..models.schemas import FitnessRequest, TrainPlan
+from ..services.llm_service import get_llm
+from ..config import get_settings
+
+# ========== Agent 提示词 ==========
+PLANNER_AGENT_PROMPT = """你是健身规划专家,你的任务是根据客户的身高、体重和年龄,生成详细的健身计划。
+
+请为以下用户生成个性化的健身计划:
+- 年龄:{request.age}岁
+- 身高:{request.height}cm
+- 体重:{request.weight}kg
+
+要求:
+1. 包含训练计划(每周3-5天)
+2. 包含营养建议
+3. 包含注意事项
+4. 用中文回复,格式美观
+
+"""
+
+class FitnessPlanner:
+
+ def __init__(self):
+ print("开始初始化智能体健身规划系统")
+
+ try:
+ settings = get_settings()
+ self.llm = get_llm()
+
+ print("创建健身规划Agent")
+ self.planner_agent = SimpleAgent(
+ name="健身规划专家",
+ llm=self.llm,
+ system_prompt=PLANNER_AGENT_PROMPT
+ )
+
+ except Exception as e:
+ print(f"❌ 智能体系统初始化失败: {str(e)}")
+ import traceback
+ traceback.print_exc()
+ raise
+
+ def plan_train(self, request: FitnessRequest) -> List[TrainPlan]:
+ try:
+ print(f"\n{'=' * 60}")
+ print(f"🚀 开始智能体规划训练...")
+ print(f"身高:{request.height}")
+ print(f"体重:{request.weight}")
+ print(f"年龄:{request.age}")
+ print(f"\n{'=' * 60}")
+
+ print("制定训练计划中...")
+ planner_query = self._build_planner_query(request)
+ planner_response = self.planner_agent.run(planner_query)
+ print(f"训练规划结果: {planner_response[:300]}...\n")
+
+ # 解析响应为列表
+ train_plan_list = self._parse_response(planner_response, request)
+
+ # 确保返回 7 天列表,如果不足则用休息日填充
+ full_plan = []
+ for day in range(1, 8):
+ day_plan = next((p for p in train_plan_list if p.get("day") == day), None)
+ if day_plan:
+ # 转换为 TrainPlan 对象
+ full_plan.append(TrainPlan(**day_plan))
+ else:
+ # 休息日占位
+ full_plan.append(TrainPlan(
+ day=day,
+ action="休息",
+ muscle=None,
+ group_num=None,
+ amount=None
+ ))
+
+ print(f"{'=' * 60}")
+ print(f"✅ 训练计划生成完成!")
+ print(f"{'=' * 60}\n")
+
+ return full_plan
+
+ except Exception as e:
+ print(f"❌ 生成训练计划失败: {str(e)}")
+ import traceback
+ traceback.print_exc()
+ return self._create_fallback_plan(request)
+
+ def _build_planner_query(self, request: FitnessRequest) -> str:
+
+ query = f"""
+ 你是一个健身训练计划生成器,只能返回 JSON 格式。
+
+ 请根据以下信息生成 **7 天训练计划**,并严格按下面的 JSON schema 输出:
+
+ 每条数据格式必须如下:
+ {{
+ "day": int,
+ "action": str,
+ "muscle": str,
+ "group_num": int,
+ "amount": int
+ }}
+
+ 输出格式必须是一个 JSON 数组,例如:
+ [
+ {{ ... }},
+ {{ ... }},
+ ...
+ ]
+
+ 用户信息:
+ - 身高: {request.height}
+ - 体重: {request.weight}
+ - 年龄: {request.age}
+
+ 生成要求:
+ 1. 输出完整 7 天计划,每天 3~4 个动作(可拆成多条 JSON)
+ 2. 返回标准 JSON 数组
+ 3. 严禁输出解释、文字、标题,只能输出 JSON
+
+ """
+ return query
+
+ def _parse_response(self, response: str, request: FitnessRequest) -> List[dict]:
+ """
+ 解析 Agent 响应为字典列表,每个元素对应一天训练计划
+ """
+ try:
+ import json
+
+ # 提取 JSON 部分
+ if "```json" in response:
+ start = response.find("```json") + 7
+ end = response.find("```", start)
+ json_str = response[start:end].strip()
+ elif "```" in response:
+ start = response.find("```") + 3
+ end = response.find("```", start)
+ json_str = response[start:end].strip()
+ else:
+ # 尝试直接解析 JSON
+ json_str = response.strip()
+
+ data = json.loads(json_str)
+
+ # 确保返回的是列表
+ if isinstance(data, dict):
+ return [data]
+ elif isinstance(data, list):
+ return data
+ else:
+ raise ValueError("Agent 返回数据格式不正确")
+
+ except Exception as e:
+ print(f"⚠️ 解析响应失败: {str(e)}")
+ print(f" 将使用备用方案生成计划")
+ return [p.dict() for p in self._create_fallback_plan(request)]
+
+ def _create_fallback_plan(self, request: FitnessRequest) -> List[TrainPlan]:
+ """
+ 生成 7 天 fallback 计划
+ """
+ fallback = []
+ for day in range(1, 8):
+ if day % 2 == 0:
+ fallback.append(TrainPlan(day=day, action="休息", muscle=None, group_num=None, amount=None))
+ else:
+ fallback.append(TrainPlan(day=day, action="深蹲", muscle="腿部", group_num=4, amount=12))
+ return fallback
+
+
+_fitness_planner = None
+
+def get_fitness_planner_agent() -> FitnessPlanner:
+ global _fitness_planner
+
+ if _fitness_planner is None:
+ _fitness_planner = FitnessPlanner()
+
+ return _fitness_planner
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/main.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/main.py
new file mode 100644
index 00000000..51d96de8
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/main.py
@@ -0,0 +1,98 @@
+from contextlib import asynccontextmanager
+
+from fastapi import FastAPI, HTTPException
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.responses import RedirectResponse
+from ..config import get_settings, valid_config, print_config
+from .routers import train
+import asyncio
+
+settings = get_settings()
+
+app = FastAPI(
+ title=settings.app_name,
+ version=settings.app_version,
+ description="基于HelloAgents框架的健身助手Agent",
+ docs_url="/docs",
+ redoc_url="/redoc"
+)
+
+# 配置CORS
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=settings.get_cors_origins(),
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"]
+)
+
+# 注册路由
+app.include_router(train.router)
+
+@app.on_event("startup")
+async def startup_event():
+ """应用启动事件"""
+ print("\n" + "=" * 60)
+ print(f"🚀 {settings.app_name} v{settings.app_version}")
+ print("=" * 60)
+
+ # 打印config配置信息
+ print_config()
+
+ # 验证配置
+ try:
+ valid_config()
+ print("\n ✔验证通过")
+ except ValueError as e:
+ print(f"\n❌ 配置验证失败:\n{e}")
+ print("\n请检查.env文件并确保所有必要的配置项都已设置")
+ raise
+
+ print("\n" + "=" * 60)
+ print("📚 API文档: http://localhost:8000/docs")
+ print("📖 ReDoc文档: http://localhost:8000/redoc")
+ print("=" * 60 + "\n")
+
+@app.on_event("shutdown")
+async def shutdown_event():
+ """应用关闭事件"""
+ print("\n" + "="*60)
+ print("👋 应用正在关闭...")
+ print("="*60 + "\n")
+
+# @app.get("/")
+# async def root():
+# """根路径"""
+# return {
+# "name": settings.app_name,
+# "version": settings.app_version,
+# "status": "running",
+# "docs": "/docs",
+# "redoc": "/redoc"
+# }
+
+@app.get("/")
+async def root():
+ return RedirectResponse(url="/train/")
+
+
+@app.get("/health")
+async def health():
+ """健康检查"""
+ return {
+ "status": "healthy",
+ "service": settings.app_name,
+ "version": settings.app_version
+ }
+
+
+if __name__ == "__main__":
+ import uvicorn
+
+ uvicorn.run(
+ "app.api.main:app",
+ host=settings.host,
+ port=settings.port,
+ reload=True
+ )
+
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/routers/train.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/routers/train.py
new file mode 100644
index 00000000..2ed9b35c
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/api/routers/train.py
@@ -0,0 +1,361 @@
+from fastapi import APIRouter, HTTPException
+from fastapi.responses import HTMLResponse
+from ...models.schemas import (
+ FitnessRequest,
+ FitnessResponse,
+ ErrorResponse
+)
+from ...agents.train_planner import get_fitness_planner_agent
+
+router = APIRouter(prefix="/train", tags=["训练计划"])
+
+# 前端界面HTML
+TRAINING_HTML = """
+
+
+
+
+
+ 健身计划生成器
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+
+@router.get("/", response_class=HTMLResponse)
+async def training_page():
+ """训练计划生成器页面"""
+ return TRAINING_HTML
+
+@router.post(
+ "/plan",
+ response_model=FitnessResponse,
+ summary="生成训练计划",
+ description="根据用户的基本情况生成训练计划"
+)
+
+async def plan_train(request: FitnessRequest):
+ """
+ 生成训练计划
+ :param request: 训练请求参数(个人基本数据)
+ :return:训练计划建议
+ """
+ try:
+ print(f"\n{'='*60}")
+ print(f"📥 收到训练计划制定请求:")
+ print(f" 身高: {request.height}")
+ print(f" 体重: {request.weight}")
+ print(f" 年龄: {request.age}")
+ print(f"{'='*60}\n")
+
+ # 获取agent实例
+ print("获取Agent系统")
+ agent = get_fitness_planner_agent()
+
+ # 开始生成健身计划
+ train_plan = agent.plan_train(request)
+
+ print("✅ 训练计划生成成功,准备返回响应\n")
+
+ return FitnessResponse(
+ success=True,
+ message="训练计划生成成功",
+ fitness_plan=train_plan
+ )
+
+ except Exception as e:
+ print(f"❌ 生成训练计划失败: {str(e)}")
+ import traceback
+ traceback.print_exc()
+ raise HTTPException(
+ status_code=500,
+ detail=f"生成训练计划失败: {str(e)}"
+ )
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/config.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/config.py
new file mode 100644
index 00000000..2b78c2a7
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/config.py
@@ -0,0 +1,85 @@
+"""配置管理模块"""
+
+import os
+from pathlib import Path
+from typing import List
+from pydantic_settings import BaseSettings
+from dotenv import load_dotenv
+
+# 加载环境变量
+load_dotenv(Path(__file__).parent.parent / '.env')
+
+# 尝试加载helloagents的.env文件
+helloagents_env = Path(__file__).parent.parent.parent / 'Hello-Agents' / '.env'
+if helloagents_env.exists():
+ load_dotenv(helloagents_env, override=False)
+
+class Settings(BaseSettings):
+ """应用配置"""
+ app_name: str = "HelloAgents健身规划助手"
+ app_version: str = "1.0.0"
+ debug: bool = False
+
+ # 服务器配置
+ host: str = "0.0.0.0"
+ port: int = 8000
+
+ # CORS配置 - 使用字符串,在代码中分割
+ cors_origins: str = "http://localhost:5173,http://localhost:3000,http://127.0.0.1:5173,http://127.0.0.1:3000"
+
+ # LLM配置 (从环境变量读取,由HelloAgents管理)
+ openai_api_key: str = ""
+ openai_base_url: str = "https://api.openai.com/v1"
+ openai_model: str = "gpt-4"
+
+ # 日志配置
+ log_level: str = "INFO"
+
+ class Config:
+ env_file = ".env"
+ case_sensitive = False
+ extra = "ignore"
+
+ def get_cors_origins(self) -> List[str]:
+ return [origin.strip() for origin in self.cors_origins.split(',')]
+
+settings = Settings()
+
+def get_settings() -> Settings:
+ return settings
+
+# 验证必要配置
+def valid_config():
+ errors = []
+ warnings = []
+
+ llm_api_key = os.getenv("LLM_API_KEY") or os.getenv("OPENAI_API_KEY")
+ if not llm_api_key:
+ warnings.append("LLM_API_KEY或OPENAI_API_KEY未配置,LLM功能可能无法使用")
+
+ if errors:
+ error_msg = "配置错误:\n" + "\n".join(f" - {e}" for e in errors)
+ raise ValueError(error_msg)
+
+ if warnings:
+ print("\n⚠️ 配置警告:")
+ for w in warnings:
+ print(f" - {w}")
+
+ return True
+
+def print_config():
+ """打印当前配置(隐藏敏感信息)"""
+ print(f"应用名称: {settings.app_name}")
+ print(f"版本: {settings.app_version}")
+ print(f"服务器: {settings.host}:{settings.port}")
+
+ # 检查LLM配置
+ llm_api_key = os.getenv("LLM_API_KEY") or os.getenv("OPENAI_API_KEY")
+ llm_base_url = os.getenv("LLM_BASE_URL") or settings.openai_base_url
+ llm_model = os.getenv("LLM_MODEL_ID") or settings.openai_model
+
+ print(f"LLM API Key: {'已配置' if llm_api_key else '未配置'}")
+ print(f"LLM Base URL: {llm_base_url}")
+ print(f"LLM Model: {llm_model}")
+ print(f"日志级别: {settings.log_level}")
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/models/schemas.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/models/schemas.py
new file mode 100644
index 00000000..51b2adfc
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/models/schemas.py
@@ -0,0 +1,38 @@
+from typing import Dict, Optional, Union, List
+from pydantic import BaseModel, Field, field_validator
+
+# ========== 请求模型 ==========
+class FitnessRequest(BaseModel):
+ """运动计划请求"""
+ height: int = Field(..., description="身高", examples=183)
+ weight: int = Field(..., description="体重", examples=76)
+ age: int = Field(..., description="年龄", examples=26)
+
+ class Config:
+ json_schema_extra = {
+ "example": {
+ "height": 183,
+ "weight": 76,
+ "age": 26
+ }
+ }
+
+# ========== 单日训练计划模型 ==========
+class TrainPlan(BaseModel):
+ day: int = Field(..., description="训练日(1~7)")
+ action: str = Field(..., description="训练动作")
+ muscle: str = Field(default=None, description="肌肉群")
+ group_num: int = Field(default=None, description="组数")
+ amount: int = Field(default=None, description="每组数量")
+
+# ========== 响应模型(支持 7 天列表) ==========
+class FitnessResponse(BaseModel):
+ success: bool = Field(..., description="是否成功")
+ message: str = Field(..., description="消息")
+ fitness_plan: List[TrainPlan] = Field(..., description="7 天训练计划")
+
+# ========== 错误响应 ==========
+class ErrorResponse(BaseModel):
+ success: bool = Field(default=False, description="是否成功")
+ message: str = Field(..., description="错误消息")
+ error_code: Optional[str] = Field(default=None, description="错误代码")
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/run_demo.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/run_demo.py
new file mode 100644
index 00000000..850fdfa9
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/run_demo.py
@@ -0,0 +1,16 @@
+"""启动脚本"""
+
+import uvicorn
+from .config import get_settings
+
+if __name__ == "__main__":
+ settings = get_settings()
+
+ uvicorn.run(
+ "app.api.main:app",
+ host=settings.host,
+ port=settings.port,
+ reload=True,
+ log_level=settings.log_level.lower()
+ )
+
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/services/llm_service.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/services/llm_service.py
new file mode 100644
index 00000000..5bb65b40
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/app/services/llm_service.py
@@ -0,0 +1,23 @@
+from hello_agents.core import HelloAgentsLLM
+from ..config import get_settings
+
+_llm_instance = None
+
+def get_llm() -> HelloAgentsLLM:
+ global _llm_instance
+
+ if _llm_instance is None:
+ settings = get_settings()
+
+ _llm_instance = HelloAgentsLLM()
+
+ print(f"✅ LLM服务初始化成功")
+ print(f" 提供商: {_llm_instance.provider}")
+ print(f" 模型: {_llm_instance.model}")
+
+ return _llm_instance
+
+def reset_llm():
+ """重置LLM实例(用于测试或重新配置)"""
+ global _llm_instance
+ _llm_instance = None
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/requirements.txt b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/requirements.txt
new file mode 100644
index 00000000..33151dc2
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/requirements.txt
@@ -0,0 +1,29 @@
+# HelloAgents框架
+hello-agents[protocols]>=0.2.4
+
+# FastAPI和相关依赖
+fastapi>=0.115.0
+uvicorn[standard]>=0.32.0
+pydantic>=2.0.0
+pydantic-settings>=2.0.0
+
+# HTTP客户端
+httpx>=0.27.0
+aiohttp>=3.10.0
+
+# 环境变量管理
+python-dotenv>=1.0.0
+
+# CORS支持
+python-multipart>=0.0.9
+
+# 日志
+loguru>=0.7.0
+
+# MCP相关
+fastmcp>=2.0.0
+uv>=0.8.0
+
+# 其他工具
+python-dateutil>=2.8.2
+huggingface-hub>=1.1.5
\ No newline at end of file
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/Activate.ps1 b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/Activate.ps1
new file mode 100644
index 00000000..918eac3e
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/Activate.ps1
@@ -0,0 +1,528 @@
+<#
+.Synopsis
+Activate a Python virtual environment for the current PowerShell session.
+
+.Description
+Pushes the python executable for a virtual environment to the front of the
+$Env:PATH environment variable and sets the prompt to signify that you are
+in a Python virtual environment. Makes use of the command line switches as
+well as the `pyvenv.cfg` file values present in the virtual environment.
+
+.Parameter VenvDir
+Path to the directory that contains the virtual environment to activate. The
+default value for this is the parent of the directory that the Activate.ps1
+script is located within.
+
+.Parameter Prompt
+The prompt prefix to display when this virtual environment is activated. By
+default, this prompt is the name of the virtual environment folder (VenvDir)
+surrounded by parentheses and followed by a single space (ie. '(.venv) ').
+
+.Example
+Activate.ps1
+Activates the Python virtual environment that contains the Activate.ps1 script.
+
+.Example
+Activate.ps1 -Verbose
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and shows extra information about the activation as it executes.
+
+.Example
+Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
+Activates the Python virtual environment located in the specified location.
+
+.Example
+Activate.ps1 -Prompt "MyPython"
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and prefixes the current prompt with the specified string (surrounded in
+parentheses) while the virtual environment is active.
+
+.Notes
+On Windows, it may be required to enable this Activate.ps1 script by setting the
+execution policy for the user. You can do this by issuing the following PowerShell
+command:
+
+PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+
+For more information on Execution Policies:
+https://go.microsoft.com/fwlink/?LinkID=135170
+
+#>
+Param(
+ [Parameter(Mandatory = $false)]
+ [String]
+ $VenvDir,
+ [Parameter(Mandatory = $false)]
+ [String]
+ $Prompt
+)
+
+<# Function declarations --------------------------------------------------- #>
+
+<#
+.Synopsis
+Remove all shell session elements added by the Activate script, including the
+addition of the virtual environment's Python executable from the beginning of
+the PATH variable.
+
+.Parameter NonDestructive
+If present, do not remove this function from the global namespace for the
+session.
+
+#>
+function global:deactivate ([switch]$NonDestructive) {
+ # Revert to original values
+
+ # The prior prompt:
+ if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
+ Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
+ Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
+ }
+
+ # The prior PYTHONHOME:
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
+ Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
+ Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
+ }
+
+ # The prior PATH:
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
+ Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
+ Remove-Item -Path Env:_OLD_VIRTUAL_PATH
+ }
+
+ # Just remove the VIRTUAL_ENV altogether:
+ if (Test-Path -Path Env:VIRTUAL_ENV) {
+ Remove-Item -Path env:VIRTUAL_ENV
+ }
+
+ # Just remove VIRTUAL_ENV_PROMPT altogether.
+ if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
+ Remove-Item -Path env:VIRTUAL_ENV_PROMPT
+ }
+
+ # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
+ if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
+ Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
+ }
+
+ # Leave deactivate function in the global namespace if requested:
+ if (-not $NonDestructive) {
+ Remove-Item -Path function:deactivate
+ }
+}
+
+<#
+.Description
+Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
+given folder, and returns them in a map.
+
+For each line in the pyvenv.cfg file, if that line can be parsed into exactly
+two strings separated by `=` (with any amount of whitespace surrounding the =)
+then it is considered a `key = value` line. The left hand string is the key,
+the right hand is the value.
+
+If the value starts with a `'` or a `"` then the first and last character is
+stripped from the value before being captured.
+
+.Parameter ConfigDir
+Path to the directory that contains the `pyvenv.cfg` file.
+#>
+function Get-PyVenvConfig(
+ [String]
+ $ConfigDir
+) {
+ Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
+
+ # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
+ $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
+
+ # An empty map will be returned if no config file is found.
+ $pyvenvConfig = @{ }
+
+ if ($pyvenvConfigPath) {
+
+ Write-Verbose "File exists, parse `key = value` lines"
+ $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
+
+ $pyvenvConfigContent | ForEach-Object {
+ $keyval = $PSItem -split "\s*=\s*", 2
+ if ($keyval[0] -and $keyval[1]) {
+ $val = $keyval[1]
+
+ # Remove extraneous quotations around a string value.
+ if ("'""".Contains($val.Substring(0, 1))) {
+ $val = $val.Substring(1, $val.Length - 2)
+ }
+
+ $pyvenvConfig[$keyval[0]] = $val
+ Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
+ }
+ }
+ }
+ return $pyvenvConfig
+}
+
+
+<# Begin Activate script --------------------------------------------------- #>
+
+# Determine the containing directory of this script
+$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
+$VenvExecDir = Get-Item -Path $VenvExecPath
+
+Write-Verbose "Activation script is located in path: '$VenvExecPath'"
+Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
+Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
+
+# Set values required in priority: CmdLine, ConfigFile, Default
+# First, get the location of the virtual environment, it might not be
+# VenvExecDir if specified on the command line.
+if ($VenvDir) {
+ Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
+}
+else {
+ Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
+ $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
+ Write-Verbose "VenvDir=$VenvDir"
+}
+
+# Next, read the `pyvenv.cfg` file to determine any required value such
+# as `prompt`.
+$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
+
+# Next, set the prompt from the command line, or the config file, or
+# just use the name of the virtual environment folder.
+if ($Prompt) {
+ Write-Verbose "Prompt specified as argument, using '$Prompt'"
+}
+else {
+ Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
+ if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
+ Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
+ $Prompt = $pyvenvCfg['prompt'];
+ }
+ else {
+ Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
+ Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
+ $Prompt = Split-Path -Path $venvDir -Leaf
+ }
+}
+
+Write-Verbose "Prompt = '$Prompt'"
+Write-Verbose "VenvDir='$VenvDir'"
+
+# Deactivate any currently active virtual environment, but leave the
+# deactivate function in place.
+deactivate -nondestructive
+
+# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
+# that there is an activated venv.
+$env:VIRTUAL_ENV = $VenvDir
+
+if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
+
+ Write-Verbose "Setting prompt to '$Prompt'"
+
+ # Set the prompt to include the env name
+ # Make sure _OLD_VIRTUAL_PROMPT is global
+ function global:_OLD_VIRTUAL_PROMPT { "" }
+ Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
+ New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
+
+ function global:prompt {
+ Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
+ _OLD_VIRTUAL_PROMPT
+ }
+ $env:VIRTUAL_ENV_PROMPT = $Prompt
+}
+
+# Clear PYTHONHOME
+if (Test-Path -Path Env:PYTHONHOME) {
+ Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
+ Remove-Item -Path Env:PYTHONHOME
+}
+
+# Add the venv to the PATH
+Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
+$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
+
+# SIG # Begin signature block
+# MII0CQYJKoZIhvcNAQcCoIIz+jCCM/YCAQExDzANBglghkgBZQMEAgEFADB5Bgor
+# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
+# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk
+# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCG9IwggXMMIIDtKADAgECAhBUmNLR1FsZ
+# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
+# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
+# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
+# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
+# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
+# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
+# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
+# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
+# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
+# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
+# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
+# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
+# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
+# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
+# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
+# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
+# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
+# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
+# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
+# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
+# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
+# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
+# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
+# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
+# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
+# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
+# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
+# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
+# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
+# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
+# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggb+MIIE5qADAgECAhMzAAM/y2Wy
+# WWnFfpZcAAAAAz/LMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
+# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
+# RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDEwHhcNMjUwNDA4MDEwNzI0WhcNMjUwNDEx
+# MDEwNzI0WjB8MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQH
+# EwlCZWF2ZXJ0b24xIzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9u
+# MSMwIQYDVQQDExpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAaIwDQYJKoZI
+# hvcNAQEBBQADggGPADCCAYoCggGBAI0elXEcbTdGLOszMU2fzimHGM9Y4EjwFgC2
+# iGPdieHc0dK1DyEIdtnvjKxnG/KICC3J2MrhePGzMEkie3yQjx05B5leG0q8YoGU
+# m9z9K67V6k3DSXX0vQe9FbaNVuyXed31MEf/qek7Zo4ELxu8n/LO3ibURBLRHNoW
+# Dz9zr4DcU+hha0bdIL6SnKMLwHqRj59gtFFEPqXcOVO7kobkzQS3O1T5KNL/zGuW
+# UGQln7fS4YI9bj24bfrSeG/QzLgChVYScxnUgjAANfT1+SnSxrT4/esMtfbcvfID
+# BIvOWk+FPPj9IQWsAMEG/LLG4cF/pQ/TozUXKx362GJBbe6paTM/RCUTcffd83h2
+# bXo9vXO/roZYk6H0ecd2h2FFzLUQn/0i4RQQSOp6zt1eDf28h6F8ev+YYKcChph8
+# iRt32bJPcLQVbUzhehzT4C0pz6oAqPz8s0BGvlj1G6r4CY1Cs2YiMU09/Fl64pWf
+# IsA/ReaYj6yNsgQZNUcvzobK2mTxMwIDAQABo4ICGTCCAhUwDAYDVR0TAQH/BAIw
+# ADAOBgNVHQ8BAf8EBAMCB4AwPAYDVR0lBDUwMwYKKwYBBAGCN2EBAAYIKwYBBQUH
+# AwMGGysGAQQBgjdhgqKNuwqmkohkgZH0oEWCk/3hbzAdBgNVHQ4EFgQU4Y4Xr/Xn
+# zEXblXrNC0ZLdaPEJYUwHwYDVR0jBBgwFoAU6IPEM9fcnwycdpoKptTfh6ZeWO4w
+# ZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
+# cy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwQU9DJTIwQ0El
+# MjAwMS5jcmwwgaUGCCsGAQUFBwEBBIGYMIGVMGQGCCsGAQUFBzAChlhodHRwOi8v
+# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw
+# VmVyaWZpZWQlMjBDUyUyMEFPQyUyMENBJTIwMDEuY3J0MC0GCCsGAQUFBzABhiFo
+# dHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwZgYDVR0gBF8wXTBRBgwr
+# BgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu
+# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEEATANBgkqhkiG
+# 9w0BAQwFAAOCAgEAKTeVGPXsDKqQLe1OuKx6K6q711FPxNQyLOOqeenH8zybHwNo
+# k05cMk39HQ7u+R9BQIL0bWexb7wa3XeKaX06p7aY/OQs+ycvUi/fC6RGlaLWmQ9D
+# YhZn2TBz5znimvSf3P+aidCuXeDU5c8GpBFog6fjEa/k+n7TILi0spuYZ4yC9R48
+# R63/VvpLi2SqxfJbx5n92bY6driNzAntjoravF25BSejXVrdzefbnqbQnZPB39g8
+# XHygGPb0912fIuNKPLQa/uCnmYdXJnPb0ZgMxxA8fyxvL2Q30Qf5xpFDssPDElvD
+# DoAbvR24CWvuHbu+CMMr2SJUpX4RRvDioO7JeB6wZb+64MXyPUSSf6QwkKNsHPIa
+# e9tSfREh86sYn5bOA0Wd+Igk0RpA5jDRTu3GgPOPWbm1PU+VoeqThtHt6R3l17pr
+# aQ5wIuuLXgxi1K4ZWgtvXw8BtIXfZz24qCtoo0+3kEGUpEHBgkF1SClbRb8uAzx+
+# 0ROGniLPJRU20Xfn7CgipeKLcNn33JPFwQHk1zpbGS0090mi0erOQCz0S47YdHmm
+# RJcbkNIL9DeNAglTZ/TFxrYUM1NRS1Cp4e63MgBKcWh9VJNokInzzmS+bofZz+u1
+# mm8YNtiJjdT8fmizXdUEk68EXQhOs0+HBNvc9nMRK6R28MZu/J+PaUcPL84wggda
+# MIIFQqADAgECAhMzAAAABzeMW6HZW4zUAAAAAAAHMA0GCSqGSIb3DQEBDAUAMGMx
+# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAy
+# BgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIw
+# MjEwHhcNMjEwNDEzMTczMTU0WhcNMjYwNDEzMTczMTU0WjBaMQswCQYDVQQGEwJV
+# UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNy
+# b3NvZnQgSUQgVmVyaWZpZWQgQ1MgQU9DIENBIDAxMIICIjANBgkqhkiG9w0BAQEF
+# AAOCAg8AMIICCgKCAgEAt/fAAygHxbo+jxA04hNI8bz+EqbWvSu9dRgAawjCZau1
+# Y54IQal5ArpJWi8cIj0WA+mpwix8iTRguq9JELZvTMo2Z1U6AtE1Tn3mvq3mywZ9
+# SexVd+rPOTr+uda6GVgwLA80LhRf82AvrSwxmZpCH/laT08dn7+Gt0cXYVNKJORm
+# 1hSrAjjDQiZ1Jiq/SqiDoHN6PGmT5hXKs22E79MeFWYB4y0UlNqW0Z2LPNua8k0r
+# bERdiNS+nTP/xsESZUnrbmyXZaHvcyEKYK85WBz3Sr6Et8Vlbdid/pjBpcHI+Hyt
+# oaUAGE6rSWqmh7/aEZeDDUkz9uMKOGasIgYnenUk5E0b2U//bQqDv3qdhj9UJYWA
+# DNYC/3i3ixcW1VELaU+wTqXTxLAFelCi/lRHSjaWipDeE/TbBb0zTCiLnc9nmOjZ
+# PKlutMNho91wxo4itcJoIk2bPot9t+AV+UwNaDRIbcEaQaBycl9pcYwWmf0bJ4IF
+# n/CmYMVG1ekCBxByyRNkFkHmuMXLX6PMXcveE46jMr9syC3M8JHRddR4zVjd/FxB
+# nS5HOro3pg6StuEPshrp7I/Kk1cTG8yOWl8aqf6OJeAVyG4lyJ9V+ZxClYmaU5yv
+# tKYKk1FLBnEBfDWw+UAzQV0vcLp6AVx2Fc8n0vpoyudr3SwZmckJuz7R+S79BzMC
+# AwEAAaOCAg4wggIKMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAd
+# BgNVHQ4EFgQU6IPEM9fcnwycdpoKptTfh6ZeWO4wVAYDVR0gBE0wSzBJBgRVHSAA
+# MEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
+# RG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAS
+# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRI
+# ajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
+# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2ln
+# bmluZyUyMFBDQSUyMDIwMjEuY3JsMIGuBggrBgEFBQcBAQSBoTCBnjBtBggrBgEF
+# BQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy
+# b3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAy
+# MDIxLmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3AubWljcm9zb2Z0LmNv
+# bS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB3/utLItkwLTp4Nfh99vrbpSsL8NwP
+# Ij2+TBnZGL3C8etTGYs+HZUxNG+rNeZa+Rzu9oEcAZJDiGjEWytzMavD6Bih3nEW
+# FsIW4aGh4gB4n/pRPeeVrK4i1LG7jJ3kPLRhNOHZiLUQtmrF4V6IxtUFjvBnijaZ
+# 9oIxsSSQP8iHMjP92pjQrHBFWHGDbkmx+yO6Ian3QN3YmbdfewzSvnQmKbkiTibJ
+# gcJ1L0TZ7BwmsDvm+0XRsPOfFgnzhLVqZdEyWww10bflOeBKqkb3SaCNQTz8nsha
+# UZhrxVU5qNgYjaaDQQm+P2SEpBF7RolEC3lllfuL4AOGCtoNdPOWrx9vBZTXAVdT
+# E2r0IDk8+5y1kLGTLKzmNFn6kVCc5BddM7xoDWQ4aUoCRXcsBeRhsclk7kVXP+zJ
+# GPOXwjUJbnz2Kt9iF/8B6FDO4blGuGrogMpyXkuwCC2Z4XcfyMjPDhqZYAPGGTUI
+# NMtFbau5RtGG1DOWE9edCahtuPMDgByfPixvhy3sn7zUHgIC/YsOTMxVuMQi/bga
+# memo/VNKZrsZaS0nzmOxKpg9qDefj5fJ9gIHXcp2F0OHcVwe3KnEXa8kqzMDfrRl
+# /wwKrNSFn3p7g0b44Ad1ONDmWt61MLQvF54LG62i6ffhTCeoFT9Z9pbUo2gxlyTF
+# g7Bm0fgOlnRfGDCCB54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJ
+# KoZIhvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
+# b3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNh
+# dGlvbiBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIw
+# MDUyMFoXDTM2MDQwMTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1p
+# Y3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlm
+# aWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+# ADCCAgoCggIBALLwwK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3
+# qrZilYKJNqztA9OQacr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrw
+# eLoQ71lzCHkD7A4As1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9
+# rGQ//h890Q8JdjLLw0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8s
+# ZU6ZE7iRrRZywRmrKDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfW
+# o5tTgkoSMoayqoDpHOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC6
+# 9oKpRQXY9bGH6jn9NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjk
+# Vd6CGUAf0K+Jw+GE/5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHg
+# YYjHs1NbOc6brH+eKpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu
+# 0t+gCwLdN0A6cFtSRtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeL
+# zdpt32cdYKp+dhr2ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGj
+# ggI1MIICMTAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0O
+# BBYEFNlBKbAPD2Ns72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8G
+# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv
+# UmVwb3NpdG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0T
+# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYD
+# VR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
+# cmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIw
+# Q2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEE
+# gbYwgbMwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
+# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw
+# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYB
+# BQUHMAGGIWh0dHA6Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG
+# 9w0BAQwFAAOCAgEAfyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdP
+# Q4H55v7VOInnmezQEeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVI
+# E1CRFfNF4XKO8XYEa3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T
+# 8FG7/VEURIVWArbAzPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4
+# e0ejRA7mB2IoX5hNh3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaB
+# jhWmirYyANb0RJSLWjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/t
+# uLjAsKP6SzYZ+1Ry358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQw
+# K8VtsBdekBmdTbQVoCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX
+# 3mccFgx6UsQeRSdVVVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQL
+# Uz6ZTl65yPUiOh3k7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i
+# 3IpaDcR+iuGjH2TdaC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxgheN
+# MIIXiQIBATBxMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
+# cG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBBT0Mg
+# Q0EgMDECEzMAAz/LZbJZacV+llwAAAADP8swDQYJYIZIAWUDBAIBBQCggcowGQYJ
+# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB
+# gjcCARUwLwYJKoZIhvcNAQkEMSIEIGcBno/ti9PCrR9sXrajsTvlHQvGxbk63JiI
+# URJByQuGMF4GCisGAQQBgjcCAQwxUDBOoEiARgBCAHUAaQBsAHQAOgAgAFIAZQBs
+# AGUAYQBzAGUAXwB2ADMALgAxADIALgAxADAAXwAyADAAMgA1ADAANAAwADgALgAw
+# ADKhAoAAMA0GCSqGSIb3DQEBAQUABIIBgE9xMVem4h5iAbvBzmB1pTdA4LYNkvd/
+# hSbYmJRt5oJqBR0RGbUmcfYAgTlhdb/S84aGvI3N62I8qeMApnH89q+UF0i8p6+U
+# Qza6Mu1cAHCq0NkHH6+N8g7nIfe5Cn+BBCBJ6kuYfQm9bx1JwEm5/yVCwG9I6+XV
+# 3WonOeA8djuZFfB9OIW6N9ubX7X+nYqWaeT6w6/lDs8mL+s0Fumy4mJ8B15pd9mr
+# N6dIRFokzhuALq6G0USKFzYf3qJQ4GyCos/Luez3cr8sE/78ds6vah5IlLP6qXMM
+# ETwAdoymIYSm3Dly3lflodd4d7/nkMhfHITOxSUDoBbCP6MO1rhChX591rJy/omK
+# 0RdM9ZpMl6VXHhzZ+lB8U/6j7xJGlxJSJHet7HFEuTnJEjY9dDy2bUgzk0vK1Rs2
+# l7VLOP3X87p9iVz5vDAOQB0fcsMDJvhIzJlmIb5z2uZ6hqD4UZdTDMLIBWe9H7Kv
+# rhmGDPHPRboFKtTrKoKcWaf4fJJ2NUtYlKGCFKAwghScBgorBgEEAYI3AwMBMYIU
+# jDCCFIgGCSqGSIb3DQEHAqCCFHkwghR1AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFh
+# BgsqhkiG9w0BCRABBKCCAVAEggFMMIIBSAIBAQYKKwYBBAGEWQoDATAxMA0GCWCG
+# SAFlAwQCAQUABCAY3nVyqXzzboHwsVGd+j5FjG9eaMv+O3mJKpX+3EJ43AIGZ9gU
+# uyvYGBMyMDI1MDQwODEyNDEyMi40MTNaMASAAgH0oIHgpIHdMIHaMQswCQYDVQQG
+# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
+# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg
+# QW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1
+# LTk2M0ItRTFGNDE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBT
+# dGFtcGluZyBBdXRob3JpdHmggg8gMIIHgjCCBWqgAwIBAgITMwAAAAXlzw//Zi7J
+# hwAAAAAABTANBgkqhkiG9w0BAQwFADB3MQswCQYDVQQGEwJVUzEeMBwGA1UEChMV
+# TWljcm9zb2Z0IENvcnBvcmF0aW9uMUgwRgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRp
+# dHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAw
+# HhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5MjA0MjMxWjBhMQswCQYDVQQGEwJVUzEe
+# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv
+# ZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDCCAiIwDQYJKoZIhvcN
+# AQEBBQADggIPADCCAgoCggIBAJ5851Jj/eDFnwV9Y7UGIqMcHtfnlzPREwW9ZUZH
+# d5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqOQxwuEQXG8kB41wsDJP5d0zmLYKAY8Zxv
+# 3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEESnt0MbPEoKdNihwM5xGv0rGofJ1qOYST
+# Ncc55EbBT7uq3wx3mXhtVmtcCEr5ZKTkKKE1CxZvNPWdGWJUPC6e4uRfWHIhZcgC
+# sJ+sozf5EeH5KrlFnxpjKKTavwfFP6XaGZGWUG8TZaiTogRoAlqcevbiqioUz1Yt
+# 4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm5sOTiEQtBLGd9Vhd1MadxoGcHrRCsS5r
+# O9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+eZ4CNE3ctW4uvSDQVeSp9h1SaPV8UWEf
+# yTxgGjOsRpeexIveR1MPTVf7gt8hY64XNPO6iyUGsEgt8c2PxF87E+CO7A28TpjN
+# q5eLiiunhKbq0XbjkNoU5JhtYUrlmAbpxRjb9tSreDdtACpm3rkpxp7AQndnI0Sh
+# u/fk1/rE3oWsDqMX3jjv40e8KN5YsJBnczyWB4JyeeFMW3JBfdeAKhzohFe8U5w9
+# WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8Y5SwB1lt5dQhABYyzR3dxEO/T1K/BVF3
+# rV69AgMBAAGjggIbMIICFzAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMC
+# AQAwHQYDVR0OBBYEFGtpKDo1L0hjQM972K9J6T7ZPdshMFQGA1UdIARNMEswSQYE
+# VR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
+# b3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJ
+# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
+# GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0
+# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl
+# bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo
+# b3JpdHklMjAyMDIwLmNybDCBlAYIKwYBBQUHAQEEgYcwgYQwgYEGCCsGAQUFBzAC
+# hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m
+# dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl
+# JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwDQYJKoZIhvcNAQEMBQADggIBAF+Idsd+
+# bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/pO+4ge/XEizXvhs0Y7+KVYyb4nHlugBes
+# nFqBGEdC2IWmtKMyS1OWIviwpnK3aL5JedwzbeBF7POyg6IGG/XhhJ3UqWeWTO+C
+# zb1c2NP5zyEh89F72u9UIw+IfvM9lzDmc2O2END7MPnrcjWdQnrLn1Ntday7JSyr
+# DvBdmgbNnCKNZPmhzoa8PccOiQljjTW6GePe5sGFuRHzdFt8y+bN2neF7Zu8hTO1
+# I64XNGqst8S+w+RUdie8fXC1jKu3m9KGIqF4aldrYBamyh3g4nJPj/LR2CBaLyD+
+# 2BuGZCVmoNR/dSpRCxlot0i79dKOChmoONqbMI8m04uLaEHAv4qwKHQ1vBzbV/nG
+# 89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFfR4f/gksSkbJp7oqLwliDm/h+w0aJ/U5c
+# cnYhYb7vPKNMN+SZDWycU5ODIRfyoGl59BsXR/HpRGtiJquOYGmvA/pk5vC1lcnb
+# eMrcWD/26ozePQ/TWfNXKBOmkFpvPE8CH+EeGGWzqTCjdAsno2jzTeNSxlx3glDG
+# Jgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqPTXPmaCAJKVHAP19oEjJIBwD1LyHbaEgB
+# xFCogYSOiUIr0Xqcr1nJfiWG2GwYe6ZoAF1bMIIHljCCBX6gAwIBAgITMwAAAEYX
+# 5HV6yv3a5QAAAAAARjANBgkqhkiG9w0BAQwFADBhMQswCQYDVQQGEwJVUzEeMBwG
+# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQg
+# UHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAeFw0yNDExMjYxODQ4NDla
+# Fw0yNTExMTkxODQ4NDlaMIHaMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
+# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
+# cmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYw
+# JAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1LTk2M0ItRTFGNDE1MDMGA1UEAxMs
+# TWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHkwggIi
+# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwlXzoj/MNL1BfnV+gg4d0fZum
+# 1HdUJidSNTcDzpHJvmIBqH566zBYcV0TyN7+3qOnJjpoTx6JBMgNYnL5BmTX9Hrm
+# X0WdNMLf74u7NtBSuAD2sf6n2qUUrz7i8f7r0JiZixKJnkvA/1akLHppQMDCug1o
+# C0AYjd753b5vy1vWdrHXE9hL71BZe5DCq5/4LBny8aOQZlzvjewgONkiZm+Sfctk
+# Jjh9LxdkDlq5EvGE6YU0uC37XF7qkHvIksD2+XgBP0lEMfmPJo2fI9FwIA9YMX7K
+# IINEM5OY6nkvKryM9s5bK6LV4z48NYpiI1xvH15YDps+19nHCtKMVTZdB4cYhA0d
+# VqJ7dAu4VcxUwD1AEcMxWbIOR1z6OFkVY9GX5oH8k17d9t35PWfn0XuxW4SG/rim
+# gtFgpE/shRsy5nMCbHyeCdW0He1plrYQqTsSHP2n/lz2DCgIlnx+uvPLVf5+JG/1
+# d1i/LdwbC2WH6UEEJyZIl3a0YwM4rdzoR+P4dO9I/2oWOxXCYqFytYdCy9ljELUw
+# byLjrjRddteR8QTxrCfadKpKfFY6Ak/HNZPUHaAPak3baOIvV7Q8axo3DWQy2ib3
+# zXV6hMPNt1v90pv+q9daQdwUzUrgcbwThdrRhWHwlRIVg2sR668HPn4/8l9ikGok
+# rL6gAmVxNswEZ9awCwIDAQABo4IByzCCAccwHQYDVR0OBBYEFBE20NSvdrC6Z6cm
+# 6RPGP8YbqIrxMB8GA1UdIwQYMBaAFGtpKDo1L0hjQM972K9J6T7ZPdshMGwGA1Ud
+# HwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js
+# L01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIw
+# MjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUFBzAChl1odHRwOi8vd3d3
+# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFB1YmxpYyUy
+# MFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5jcnQwDAYDVR0TAQH/BAIw
+# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0g
+# BF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t
+# aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEE
+# AjANBgkqhkiG9w0BAQwFAAOCAgEAFIW5L+gGzX4gyHorS33YKXuK9iC91iZTpm30
+# x/EdHG6U8NAu2qityxjZVq6MDq300gspG0ntzLYqVhjfku7iNzE78k6tNgFCr9wv
+# GkIHeK+Q2RAO9/s5R8rhNC+lywOB+6K5Zi0kfO0agVXf7Nk2O6F6D9AEzNLijG+c
+# Oe5Ef2F5l4ZsVSkLFCI5jELC+r4KnNZjunc+qvjSz2DkNsXfrjFhyk+K7v7U7+JF
+# Z8kZ58yFuxEX0cxDKpJLxiNh/ODCOL2UxYkhyfI3AR0EhfxX9QZHVgxyZwnavR35
+# FxqLSiGTeAJsK7YN3bIxyuP6eCcnkX8TMdpu9kPD97sHnM7po0UQDrjaN7etviLD
+# xnax2nemdvJW3BewOLFrD1nSnd7ZHdPGPB3oWTCaK9/3XwQERLi3Xj+HZc89RP50
+# Nt7h7+3G6oq2kXYNidI9iWd+gL+lvkQZH9YTIfBCLWjvuXvUUUU+AvFI00Utqrvd
+# rIdqCFaqE9HHQgSfXeQ53xLWdMCztUP/YnMXiJxNBkc6UE2px/o6+/LXJDIpwIXR
+# 4HSodLfkfsNQl6FFrJ1xsOYGSHvcFkH8389RmUvrjr1NBbdesc4Bu4kox+3cabOZ
+# c1zm89G+1RRL2tReFzSMlYSGO3iKn3GGXmQiRmFlBb3CpbUVQz+fgxVMfeL0j4Lm
+# KQfT1jIxggPUMIID0AIBATB4MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
+# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNB
+# IFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAARhfkdXrK/drlAAAAAABGMA0GCWCG
+# SAFlAwQCAQUAoIIBLTAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI
+# hvcNAQkEMSIEIHgwQkiMhul6IrfEKmPaCFR+R91oZOlPqVgP/9PPcfn+MIHdBgsq
+# hkiG9w0BCRACLzGBzTCByjCBxzCBoAQgEid2SJpUPj5xQm73M4vqDmVh1QR6TiuT
+# UVkL3P8Wis4wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m
+# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGlt
+# ZXN0YW1waW5nIENBIDIwMjACEzMAAABGF+R1esr92uUAAAAAAEYwIgQgVp6I1YBM
+# Mni0rCuD57vEK/tzWZypHqWFikWLFVY11RwwDQYJKoZIhvcNAQELBQAEggIAnRBH
+# voM5+wbJp+aOwrrL8fi8Rv/eFV820Nhr+jMny73UscN60OWdcdcZDbjDlnDX1KEP
+# sNcEOFvaruHHrF4kDK8N0yemElNz63IgqhUoGoXXQKT2RgVg7T/kiQJH7zuaEjgB
+# YNniAZdXXJJ1C+uv2ZQzkGIEVIEA6pB5/xo4kFhrfkOrdGzqL8HXT/RZQDMn5Uzk
+# W+Sl2JmsyYBS4sgI9Ay3qT5nv+frzngbWlqx1dre21uj37Fgk5mWHJEdmY1nqTTd
+# 25j6oDLGPC8AS9wtgZBXggemKAXwyeOFFahXUFN7X7cbwTALy5aWjE/rqp+N5J7M
+# +YApl3aknUZ13KTXz9pfAF0uhmZimngvBHjijyctleF8HUP2RNAhS/l68OqW7oKi
+# Dqvb7tSHJbcnYkxo7dUq6ppfN51ah61ZsyMVG6SaH015+5QO1k50ohXcFff2GOuZ
+# d3Z9JOoAjIkeiVTNeRlPDlHtS0CSYu4ZKsWsst+0VY2R9rJBeoii9Xa0oiIggkYL
+# 1pHAPH0B1uLlvFcI6B+fAXe0OiCJodbO5lk8ZpvCG5WWYbjzp2c3B8PZGSBgEpSf
+# KYlVavvBAvaJCORUO7j8PyzzDINuzQorP9+i399ORjOnqeC92Cb0V12LcoqqtJaf
+# 7oSB86VOI0lfHnPUlLWvoiLHrFR5PsYkltOuPqU=
+# SIG # End signature block
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate
new file mode 100644
index 00000000..9dce461c
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate
@@ -0,0 +1,76 @@
+# This file must be used with "source bin/activate" *from bash*
+# You cannot run it directly
+
+deactivate () {
+ # reset old environment variables
+ if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
+ PATH="${_OLD_VIRTUAL_PATH:-}"
+ export PATH
+ unset _OLD_VIRTUAL_PATH
+ fi
+ if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
+ PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
+ export PYTHONHOME
+ unset _OLD_VIRTUAL_PYTHONHOME
+ fi
+
+ # Call hash to forget past locations. Without forgetting
+ # past locations the $PATH changes we made may not be respected.
+ # See "man bash" for more details. hash is usually a builtin of your shell
+ hash -r 2> /dev/null
+
+ if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
+ PS1="${_OLD_VIRTUAL_PS1:-}"
+ export PS1
+ unset _OLD_VIRTUAL_PS1
+ fi
+
+ unset VIRTUAL_ENV
+ unset VIRTUAL_ENV_PROMPT
+ if [ ! "${1:-}" = "nondestructive" ] ; then
+ # Self destruct!
+ unset -f deactivate
+ fi
+}
+
+# unset irrelevant variables
+deactivate nondestructive
+
+# on Windows, a path can contain colons and backslashes and has to be converted:
+case "$(uname)" in
+ CYGWIN*|MSYS*|MINGW*)
+ # transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW
+ # and to /cygdrive/d/path/to/venv on Cygwin
+ VIRTUAL_ENV=$(cygpath 'D:\pythonProject\smart_fitness_planner\venv_fit')
+ export VIRTUAL_ENV
+ ;;
+ *)
+ # use the path as-is
+ export VIRTUAL_ENV='D:\pythonProject\smart_fitness_planner\venv_fit'
+ ;;
+esac
+
+_OLD_VIRTUAL_PATH="$PATH"
+PATH="$VIRTUAL_ENV/"Scripts":$PATH"
+export PATH
+
+VIRTUAL_ENV_PROMPT='(venv_fit) '
+export VIRTUAL_ENV_PROMPT
+
+# unset PYTHONHOME if set
+# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
+# could use `if (set -u; : $PYTHONHOME) ;` in bash
+if [ -n "${PYTHONHOME:-}" ] ; then
+ _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
+ unset PYTHONHOME
+fi
+
+if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
+ _OLD_VIRTUAL_PS1="${PS1:-}"
+ PS1="("'(venv_fit) '") ${PS1:-}"
+ export PS1
+fi
+
+# Call hash to forget past commands. Without forgetting
+# past commands the $PATH changes we made may not be respected
+hash -r 2> /dev/null
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate.bat b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate.bat
new file mode 100644
index 00000000..7974de0e
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/activate.bat
@@ -0,0 +1,34 @@
+@echo off
+
+rem This file is UTF-8 encoded, so we need to update the current code page while executing it
+for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (
+ set _OLD_CODEPAGE=%%a
+)
+if defined _OLD_CODEPAGE (
+ "%SystemRoot%\System32\chcp.com" 65001 > nul
+)
+
+set "VIRTUAL_ENV=D:\pythonProject\smart_fitness_planner\venv_fit"
+
+if not defined PROMPT set PROMPT=$P$G
+
+if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%
+if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%
+
+set _OLD_VIRTUAL_PROMPT=%PROMPT%
+set PROMPT=(venv_fit) %PROMPT%
+
+if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
+set PYTHONHOME=
+
+if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
+if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
+
+set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%"
+set "VIRTUAL_ENV_PROMPT=(venv_fit) "
+
+:END
+if defined _OLD_CODEPAGE (
+ "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul
+ set _OLD_CODEPAGE=
+)
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/cyclopts.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/cyclopts.exe
new file mode 100644
index 00000000..b9ae2889
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/cyclopts.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/deactivate.bat b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/deactivate.bat
new file mode 100644
index 00000000..62a39a75
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/deactivate.bat
@@ -0,0 +1,22 @@
+@echo off
+
+if defined _OLD_VIRTUAL_PROMPT (
+ set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
+)
+set _OLD_VIRTUAL_PROMPT=
+
+if defined _OLD_VIRTUAL_PYTHONHOME (
+ set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
+ set _OLD_VIRTUAL_PYTHONHOME=
+)
+
+if defined _OLD_VIRTUAL_PATH (
+ set "PATH=%_OLD_VIRTUAL_PATH%"
+)
+
+set _OLD_VIRTUAL_PATH=
+
+set VIRTUAL_ENV=
+set VIRTUAL_ENV_PROMPT=
+
+:END
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/distro.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/distro.exe
new file mode 100644
index 00000000..49a84a2b
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/distro.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/docutils.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/docutils.exe
new file mode 100644
index 00000000..dddd83d9
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/docutils.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/dotenv.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/dotenv.exe
new file mode 100644
index 00000000..79a6df3e
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/dotenv.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/email_validator.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/email_validator.exe
new file mode 100644
index 00000000..a0668704
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/email_validator.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/f2py.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/f2py.exe
new file mode 100644
index 00000000..6078b7ee
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/f2py.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastapi.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastapi.exe
new file mode 100644
index 00000000..f5ec0746
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastapi.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastmcp.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastmcp.exe
new file mode 100644
index 00000000..8847fe1e
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/fastmcp.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/hf.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/hf.exe
new file mode 100644
index 00000000..4656a845
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/hf.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/httpx.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/httpx.exe
new file mode 100644
index 00000000..f41e32b5
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/httpx.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/jsonschema.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/jsonschema.exe
new file mode 100644
index 00000000..ef1bb2c4
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/jsonschema.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/keyring.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/keyring.exe
new file mode 100644
index 00000000..f6399329
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/keyring.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/markdown-it.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/markdown-it.exe
new file mode 100644
index 00000000..c492b770
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/markdown-it.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/mcp.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/mcp.exe
new file mode 100644
index 00000000..d16c0245
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/mcp.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/normalizer.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/normalizer.exe
new file mode 100644
index 00000000..f075a90a
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/normalizer.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/numpy-config.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/numpy-config.exe
new file mode 100644
index 00000000..09d39831
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/numpy-config.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/openai.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/openai.exe
new file mode 100644
index 00000000..a1bfbe85
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/openai.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip.exe
new file mode 100644
index 00000000..f5226160
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.12.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.12.exe
new file mode 100644
index 00000000..f5226160
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.12.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.exe
new file mode 100644
index 00000000..f5226160
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pip3.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pygmentize.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pygmentize.exe
new file mode 100644
index 00000000..9b859a90
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pygmentize.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-decrypt.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-decrypt.exe
new file mode 100644
index 00000000..60992ce7
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-decrypt.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-encrypt.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-encrypt.exe
new file mode 100644
index 00000000..1ed7e769
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-encrypt.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-keygen.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-keygen.exe
new file mode 100644
index 00000000..91e2cde9
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-keygen.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-priv2pub.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-priv2pub.exe
new file mode 100644
index 00000000..59fde908
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-priv2pub.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-sign.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-sign.exe
new file mode 100644
index 00000000..9e0c527e
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-sign.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-verify.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-verify.exe
new file mode 100644
index 00000000..bc4c4d34
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pyrsa-verify.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/python.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/python.exe
new file mode 100644
index 00000000..ba0cd040
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/python.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pythonw.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pythonw.exe
new file mode 100644
index 00000000..68b3cfe9
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pythonw.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.exe
new file mode 100644
index 00000000..f8927b8f
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.py
new file mode 100644
index 00000000..3348b8cd
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_postinstall.py
@@ -0,0 +1,733 @@
+# postinstall script for pywin32
+#
+# copies pywintypesXX.dll and pythoncomXX.dll into the system directory,
+# and creates a pth file
+import argparse
+import glob
+import os
+import shutil
+import sys
+import sysconfig
+import tempfile
+import winreg
+
+tee_f = open(
+ os.path.join(
+ tempfile.gettempdir(), # Send output somewhere so it can be found if necessary...
+ "pywin32_postinstall.log",
+ ),
+ "w",
+)
+
+
+class Tee:
+ def __init__(self, file):
+ self.f = file
+
+ def write(self, what):
+ if self.f is not None:
+ try:
+ self.f.write(what.replace("\n", "\r\n"))
+ except OSError:
+ pass
+ tee_f.write(what)
+
+ def flush(self):
+ if self.f is not None:
+ try:
+ self.f.flush()
+ except OSError:
+ pass
+ tee_f.flush()
+
+
+sys.stderr = Tee(sys.stderr)
+sys.stdout = Tee(sys.stdout)
+
+com_modules = [
+ # module_name, class_names
+ ("win32com.servers.interp", "Interpreter"),
+ ("win32com.servers.dictionary", "DictionaryPolicy"),
+ ("win32com.axscript.client.pyscript", "PyScript"),
+]
+
+# Is this a 'silent' install - ie, avoid all dialogs.
+# Different than 'verbose'
+silent = 0
+
+# Verbosity of output messages.
+verbose = 1
+
+root_key_name = "Software\\Python\\PythonCore\\" + sys.winver
+
+
+def get_root_hkey():
+ try:
+ winreg.OpenKey(
+ winreg.HKEY_LOCAL_MACHINE, root_key_name, 0, winreg.KEY_CREATE_SUB_KEY
+ )
+ return winreg.HKEY_LOCAL_MACHINE
+ except OSError:
+ # Either not exist, or no permissions to create subkey means
+ # must be HKCU
+ return winreg.HKEY_CURRENT_USER
+
+
+# Create a function with the same signature as create_shortcut
+# previously provided by bdist_wininst
+def create_shortcut(
+ path, description, filename, arguments="", workdir="", iconpath="", iconindex=0
+):
+ import pythoncom
+ from win32com.shell import shell
+
+ ilink = pythoncom.CoCreateInstance(
+ shell.CLSID_ShellLink,
+ None,
+ pythoncom.CLSCTX_INPROC_SERVER,
+ shell.IID_IShellLink,
+ )
+ ilink.SetPath(path)
+ ilink.SetDescription(description)
+ if arguments:
+ ilink.SetArguments(arguments)
+ if workdir:
+ ilink.SetWorkingDirectory(workdir)
+ if iconpath or iconindex:
+ ilink.SetIconLocation(iconpath, iconindex)
+ # now save it.
+ ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile)
+ ipf.Save(filename, 0)
+
+
+# Support the same list of "path names" as bdist_wininst used to
+def get_special_folder_path(path_name):
+ from win32com.shell import shell, shellcon
+
+ for maybe in """
+ CSIDL_COMMON_STARTMENU CSIDL_STARTMENU CSIDL_COMMON_APPDATA
+ CSIDL_LOCAL_APPDATA CSIDL_APPDATA CSIDL_COMMON_DESKTOPDIRECTORY
+ CSIDL_DESKTOPDIRECTORY CSIDL_COMMON_STARTUP CSIDL_STARTUP
+ CSIDL_COMMON_PROGRAMS CSIDL_PROGRAMS CSIDL_PROGRAM_FILES_COMMON
+ CSIDL_PROGRAM_FILES CSIDL_FONTS""".split():
+ if maybe == path_name:
+ csidl = getattr(shellcon, maybe)
+ return shell.SHGetSpecialFolderPath(0, csidl, False)
+ raise ValueError(f"{path_name} is an unknown path ID")
+
+
+def CopyTo(desc, src, dest):
+ import win32api
+ import win32con
+
+ while 1:
+ try:
+ win32api.CopyFile(src, dest, 0)
+ return
+ except win32api.error as details:
+ if details.winerror == 5: # access denied - user not admin.
+ raise
+ if silent:
+ # Running silent mode - just re-raise the error.
+ raise
+ full_desc = (
+ f"Error {desc}\n\n"
+ "If you have any Python applications running, "
+ f"please close them now\nand select 'Retry'\n\n{details.strerror}"
+ )
+ rc = win32api.MessageBox(
+ 0, full_desc, "Installation Error", win32con.MB_ABORTRETRYIGNORE
+ )
+ if rc == win32con.IDABORT:
+ raise
+ elif rc == win32con.IDIGNORE:
+ return
+ # else retry - around we go again.
+
+
+# We need to import win32api to determine the Windows system directory,
+# so we can copy our system files there - but importing win32api will
+# load the pywintypes.dll already in the system directory preventing us
+# from updating them!
+# So, we pull the same trick pywintypes.py does, but it loads from
+# our pywintypes_system32 directory.
+def LoadSystemModule(lib_dir, modname):
+ # See if this is a debug build.
+ import importlib.machinery
+ import importlib.util
+
+ suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else ""
+ filename = "%s%d%d%s.dll" % (
+ modname,
+ sys.version_info.major,
+ sys.version_info.minor,
+ suffix,
+ )
+ filename = os.path.join(lib_dir, "pywin32_system32", filename)
+ loader = importlib.machinery.ExtensionFileLoader(modname, filename)
+ spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=filename)
+ mod = importlib.util.module_from_spec(spec)
+ loader.exec_module(mod)
+
+
+def SetPyKeyVal(key_name, value_name, value):
+ root_hkey = get_root_hkey()
+ root_key = winreg.OpenKey(root_hkey, root_key_name)
+ try:
+ my_key = winreg.CreateKey(root_key, key_name)
+ try:
+ winreg.SetValueEx(my_key, value_name, 0, winreg.REG_SZ, value)
+ if verbose:
+ print(f"-> {root_key_name}\\{key_name}[{value_name}]={value!r}")
+ finally:
+ my_key.Close()
+ finally:
+ root_key.Close()
+
+
+def UnsetPyKeyVal(key_name, value_name, delete_key=False):
+ root_hkey = get_root_hkey()
+ root_key = winreg.OpenKey(root_hkey, root_key_name)
+ try:
+ my_key = winreg.OpenKey(root_key, key_name, 0, winreg.KEY_SET_VALUE)
+ try:
+ winreg.DeleteValue(my_key, value_name)
+ if verbose:
+ print(f"-> DELETE {root_key_name}\\{key_name}[{value_name}]")
+ finally:
+ my_key.Close()
+ if delete_key:
+ winreg.DeleteKey(root_key, key_name)
+ if verbose:
+ print(f"-> DELETE {root_key_name}\\{key_name}")
+ except OSError as why:
+ winerror = getattr(why, "winerror", why.errno)
+ if winerror != 2: # file not found
+ raise
+ finally:
+ root_key.Close()
+
+
+def RegisterCOMObjects(register=True):
+ import win32com.server.register
+
+ if register:
+ func = win32com.server.register.RegisterClasses
+ else:
+ func = win32com.server.register.UnregisterClasses
+ flags = {}
+ if not verbose:
+ flags["quiet"] = 1
+ for module, klass_name in com_modules:
+ __import__(module)
+ mod = sys.modules[module]
+ flags["finalize_register"] = getattr(mod, "DllRegisterServer", None)
+ flags["finalize_unregister"] = getattr(mod, "DllUnregisterServer", None)
+ klass = getattr(mod, klass_name)
+ func(klass, **flags)
+
+
+def RegisterHelpFile(register=True, lib_dir=None):
+ if lib_dir is None:
+ lib_dir = sysconfig.get_paths()["platlib"]
+ if register:
+ # Register the .chm help file.
+ chm_file = os.path.join(lib_dir, "PyWin32.chm")
+ if os.path.isfile(chm_file):
+ # This isn't recursive, so if 'Help' doesn't exist, we croak
+ SetPyKeyVal("Help", None, None)
+ SetPyKeyVal("Help\\Pythonwin Reference", None, chm_file)
+ return chm_file
+ else:
+ print("NOTE: PyWin32.chm can not be located, so has not been registered")
+ else:
+ UnsetPyKeyVal("Help\\Pythonwin Reference", None, delete_key=True)
+ return None
+
+
+def RegisterPythonwin(register=True, lib_dir=None):
+ """Add (or remove) Pythonwin to context menu for python scripts.
+ ??? Should probably also add Edit command for pys files also.
+ Also need to remove these keys on uninstall, but there's no function
+ to add registry entries to uninstall log ???
+ """
+ import os
+
+ if lib_dir is None:
+ lib_dir = sysconfig.get_paths()["platlib"]
+ classes_root = get_root_hkey()
+ ## Installer executable doesn't seem to pass anything to postinstall script indicating if it's a debug build
+ pythonwin_exe = os.path.join(lib_dir, "Pythonwin", "Pythonwin.exe")
+ pythonwin_edit_command = pythonwin_exe + ' -edit "%1"'
+
+ keys_vals = [
+ (
+ "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Pythonwin.exe",
+ "",
+ pythonwin_exe,
+ ),
+ (
+ "Software\\Classes\\Python.File\\shell\\Edit with Pythonwin",
+ "command",
+ pythonwin_edit_command,
+ ),
+ (
+ "Software\\Classes\\Python.NoConFile\\shell\\Edit with Pythonwin",
+ "command",
+ pythonwin_edit_command,
+ ),
+ ]
+
+ try:
+ if register:
+ for key, sub_key, val in keys_vals:
+ ## Since winreg only uses the character Api functions, this can fail if Python
+ ## is installed to a path containing non-ascii characters
+ hkey = winreg.CreateKey(classes_root, key)
+ if sub_key:
+ hkey = winreg.CreateKey(hkey, sub_key)
+ winreg.SetValueEx(hkey, None, 0, winreg.REG_SZ, val)
+ hkey.Close()
+ else:
+ for key, sub_key, val in keys_vals:
+ try:
+ if sub_key:
+ hkey = winreg.OpenKey(classes_root, key)
+ winreg.DeleteKey(hkey, sub_key)
+ hkey.Close()
+ winreg.DeleteKey(classes_root, key)
+ except OSError as why:
+ winerror = getattr(why, "winerror", why.errno)
+ if winerror != 2: # file not found
+ raise
+ finally:
+ # tell windows about the change
+ from win32com.shell import shell, shellcon
+
+ shell.SHChangeNotify(
+ shellcon.SHCNE_ASSOCCHANGED, shellcon.SHCNF_IDLIST, None, None
+ )
+
+
+def get_shortcuts_folder():
+ if get_root_hkey() == winreg.HKEY_LOCAL_MACHINE:
+ try:
+ fldr = get_special_folder_path("CSIDL_COMMON_PROGRAMS")
+ except OSError:
+ # No CSIDL_COMMON_PROGRAMS on this platform
+ fldr = get_special_folder_path("CSIDL_PROGRAMS")
+ else:
+ # non-admin install - always goes in this user's start menu.
+ fldr = get_special_folder_path("CSIDL_PROGRAMS")
+
+ try:
+ install_group = winreg.QueryValue(
+ get_root_hkey(), root_key_name + "\\InstallPath\\InstallGroup"
+ )
+ except OSError:
+ install_group = "Python %d.%d" % (
+ sys.version_info.major,
+ sys.version_info.minor,
+ )
+ return os.path.join(fldr, install_group)
+
+
+# Get the system directory, which may be the Wow64 directory if we are a 32bit
+# python on a 64bit OS.
+def get_system_dir():
+ import win32api # we assume this exists.
+
+ try:
+ import pythoncom
+ import win32process
+ from win32com.shell import shell, shellcon
+
+ try:
+ if win32process.IsWow64Process():
+ return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEMX86)
+ return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEM)
+ except (pythoncom.com_error, win32process.error):
+ return win32api.GetSystemDirectory()
+ except ImportError:
+ return win32api.GetSystemDirectory()
+
+
+def fixup_dbi():
+ # We used to have a dbi.pyd with our .pyd files, but now have a .py file.
+ # If the user didn't uninstall, they will find the .pyd which will cause
+ # problems - so handle that.
+ import win32api
+ import win32con
+
+ pyd_name = os.path.join(os.path.dirname(win32api.__file__), "dbi.pyd")
+ pyd_d_name = os.path.join(os.path.dirname(win32api.__file__), "dbi_d.pyd")
+ py_name = os.path.join(os.path.dirname(win32con.__file__), "dbi.py")
+ for this_pyd in (pyd_name, pyd_d_name):
+ this_dest = this_pyd + ".old"
+ if os.path.isfile(this_pyd) and os.path.isfile(py_name):
+ try:
+ if os.path.isfile(this_dest):
+ print(
+ f"Old dbi '{this_dest}' already exists - deleting '{this_pyd}'"
+ )
+ os.remove(this_pyd)
+ else:
+ os.rename(this_pyd, this_dest)
+ print(f"renamed '{this_pyd}'->'{this_pyd}.old'")
+ except OSError as exc:
+ print(f"FAILED to rename '{this_pyd}': {exc}")
+
+
+def install(lib_dir):
+ import traceback
+
+ # The .pth file is now installed as a regular file.
+ # Create the .pth file in the site-packages dir, and use only relative paths
+ # We used to write a .pth directly to sys.prefix - clobber it.
+ if os.path.isfile(os.path.join(sys.prefix, "pywin32.pth")):
+ os.unlink(os.path.join(sys.prefix, "pywin32.pth"))
+ # The .pth may be new and therefore not loaded in this session.
+ # Setup the paths just in case.
+ for name in "win32 win32\\lib Pythonwin".split():
+ sys.path.append(os.path.join(lib_dir, name))
+ # It is possible people with old versions installed with still have
+ # pywintypes and pythoncom registered. We no longer need this, and stale
+ # entries hurt us.
+ for name in "pythoncom pywintypes".split():
+ keyname = "Software\\Python\\PythonCore\\" + sys.winver + "\\Modules\\" + name
+ for root in winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER:
+ try:
+ winreg.DeleteKey(root, keyname + "\\Debug")
+ except OSError:
+ pass
+ try:
+ winreg.DeleteKey(root, keyname)
+ except OSError:
+ pass
+ LoadSystemModule(lib_dir, "pywintypes")
+ LoadSystemModule(lib_dir, "pythoncom")
+ import win32api
+
+ # and now we can get the system directory:
+ files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
+ if not files:
+ raise RuntimeError("No system files to copy!!")
+ # Try the system32 directory first - if that fails due to "access denied",
+ # it implies a non-admin user, and we use sys.prefix
+ for dest_dir in [get_system_dir(), sys.prefix]:
+ # and copy some files over there
+ worked = 0
+ try:
+ for fname in files:
+ base = os.path.basename(fname)
+ dst = os.path.join(dest_dir, base)
+ CopyTo("installing %s" % base, fname, dst)
+ if verbose:
+ print(f"Copied {base} to {dst}")
+ worked = 1
+ # Nuke any other versions that may exist - having
+ # duplicates causes major headaches.
+ bad_dest_dirs = [
+ os.path.join(sys.prefix, "Library\\bin"),
+ os.path.join(sys.prefix, "Lib\\site-packages\\win32"),
+ ]
+ if dest_dir != sys.prefix:
+ bad_dest_dirs.append(sys.prefix)
+ for bad_dest_dir in bad_dest_dirs:
+ bad_fname = os.path.join(bad_dest_dir, base)
+ if os.path.exists(bad_fname):
+ # let exceptions go here - delete must succeed
+ os.unlink(bad_fname)
+ if worked:
+ break
+ except win32api.error as details:
+ if details.winerror == 5:
+ # access denied - user not admin - try sys.prefix dir,
+ # but first check that a version doesn't already exist
+ # in that place - otherwise that one will still get used!
+ if os.path.exists(dst):
+ msg = (
+ "The file '%s' exists, but can not be replaced "
+ "due to insufficient permissions. You must "
+ "reinstall this software as an Administrator" % dst
+ )
+ print(msg)
+ raise RuntimeError(msg)
+ continue
+ raise
+ else:
+ raise RuntimeError(
+ "You don't have enough permissions to install the system files"
+ )
+
+ # Register our demo COM objects.
+ try:
+ try:
+ RegisterCOMObjects()
+ except win32api.error as details:
+ if details.winerror != 5: # ERROR_ACCESS_DENIED
+ raise
+ print("You do not have the permissions to install COM objects.")
+ print("The sample COM objects were not registered.")
+ except Exception:
+ print("FAILED to register the Python COM objects")
+ traceback.print_exc()
+
+ # There may be no main Python key in HKCU if, eg, an admin installed
+ # python itself.
+ winreg.CreateKey(get_root_hkey(), root_key_name)
+
+ chm_file = None
+ try:
+ chm_file = RegisterHelpFile(True, lib_dir)
+ except Exception:
+ print("Failed to register help file")
+ traceback.print_exc()
+ else:
+ if verbose:
+ print("Registered help file")
+
+ # misc other fixups.
+ fixup_dbi()
+
+ # Register Pythonwin in context menu
+ try:
+ RegisterPythonwin(True, lib_dir)
+ except Exception:
+ print("Failed to register pythonwin as editor")
+ traceback.print_exc()
+ else:
+ if verbose:
+ print("Pythonwin has been registered in context menu")
+
+ # Create the win32com\gen_py directory.
+ make_dir = os.path.join(lib_dir, "win32com", "gen_py")
+ if not os.path.isdir(make_dir):
+ if verbose:
+ print(f"Creating directory {make_dir}")
+ os.mkdir(make_dir)
+
+ try:
+ # create shortcuts
+ # CSIDL_COMMON_PROGRAMS only available works on NT/2000/XP, and
+ # will fail there if the user has no admin rights.
+ fldr = get_shortcuts_folder()
+ # If the group doesn't exist, then we don't make shortcuts - its
+ # possible that this isn't a "normal" install.
+ if os.path.isdir(fldr):
+ dst = os.path.join(fldr, "PythonWin.lnk")
+ create_shortcut(
+ os.path.join(lib_dir, "Pythonwin\\Pythonwin.exe"),
+ "The Pythonwin IDE",
+ dst,
+ "",
+ sys.prefix,
+ )
+ if verbose:
+ print("Shortcut for Pythonwin created")
+ # And the docs.
+ if chm_file:
+ dst = os.path.join(fldr, "Python for Windows Documentation.lnk")
+ doc = "Documentation for the PyWin32 extensions"
+ create_shortcut(chm_file, doc, dst)
+ if verbose:
+ print("Shortcut to documentation created")
+ else:
+ if verbose:
+ print(f"Can't install shortcuts - {fldr!r} is not a folder")
+ except Exception as details:
+ print(details)
+
+ # importing win32com.client ensures the gen_py dir created - not strictly
+ # necessary to do now, but this makes the installation "complete"
+ try:
+ import win32com.client # noqa
+ except ImportError:
+ # Don't let this error sound fatal
+ pass
+ print("The pywin32 extensions were successfully installed.")
+
+
+def uninstall(lib_dir):
+ # First ensure our system modules are loaded from pywin32_system, so
+ # we can remove the ones we copied...
+ LoadSystemModule(lib_dir, "pywintypes")
+ LoadSystemModule(lib_dir, "pythoncom")
+
+ try:
+ RegisterCOMObjects(False)
+ except Exception as why:
+ print(f"Failed to unregister COM objects: {why}")
+
+ try:
+ RegisterHelpFile(False, lib_dir)
+ except Exception as why:
+ print(f"Failed to unregister help file: {why}")
+ else:
+ if verbose:
+ print("Unregistered help file")
+
+ try:
+ RegisterPythonwin(False, lib_dir)
+ except Exception as why:
+ print(f"Failed to unregister Pythonwin: {why}")
+ else:
+ if verbose:
+ print("Unregistered Pythonwin")
+
+ try:
+ # remove gen_py directory.
+ gen_dir = os.path.join(lib_dir, "win32com", "gen_py")
+ if os.path.isdir(gen_dir):
+ shutil.rmtree(gen_dir)
+ if verbose:
+ print(f"Removed directory {gen_dir}")
+
+ # Remove pythonwin compiled "config" files.
+ pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin")
+ for fname in glob.glob(os.path.join(pywin_dir, "*.cfc")):
+ os.remove(fname)
+
+ # The dbi.pyd.old files we may have created.
+ try:
+ os.remove(os.path.join(lib_dir, "win32", "dbi.pyd.old"))
+ except OSError:
+ pass
+ try:
+ os.remove(os.path.join(lib_dir, "win32", "dbi_d.pyd.old"))
+ except OSError:
+ pass
+
+ except Exception as why:
+ print(f"Failed to remove misc files: {why}")
+
+ try:
+ fldr = get_shortcuts_folder()
+ for link in ("PythonWin.lnk", "Python for Windows Documentation.lnk"):
+ fqlink = os.path.join(fldr, link)
+ if os.path.isfile(fqlink):
+ os.remove(fqlink)
+ if verbose:
+ print(f"Removed {link}")
+ except Exception as why:
+ print(f"Failed to remove shortcuts: {why}")
+ # Now remove the system32 files.
+ files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
+ # Try the system32 directory first - if that fails due to "access denied",
+ # it implies a non-admin user, and we use sys.prefix
+ try:
+ for dest_dir in [get_system_dir(), sys.prefix]:
+ # and copy some files over there
+ worked = 0
+ for fname in files:
+ base = os.path.basename(fname)
+ dst = os.path.join(dest_dir, base)
+ if os.path.isfile(dst):
+ try:
+ os.remove(dst)
+ worked = 1
+ if verbose:
+ print("Removed file %s" % (dst))
+ except Exception:
+ print(f"FAILED to remove {dst}")
+ if worked:
+ break
+ except Exception as why:
+ print(f"FAILED to remove system files: {why}")
+
+
+# NOTE: This used to be run from inside the bdist_wininst created binary un/installer.
+# From inside the binary installer this script HAD to NOT
+# call sys.exit() or raise SystemExit, otherwise the installer would also terminate!
+# Out of principle, we're still not using system exits.
+
+
+def verify_destination(location: str) -> str:
+ location = os.path.abspath(location)
+ if not os.path.isdir(location):
+ raise argparse.ArgumentTypeError(
+ f'Path "{location}" is not an existing directory!'
+ )
+ return location
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""A post-install script for the pywin32 extensions.
+
+ * Typical usage:
+
+ > python -m pywin32_postinstall -install
+
+ * or (shorter but you don't have control over which python environment is used)
+
+ > pywin32_postinstall -install
+
+ You need to execute this script, with a '-install' parameter,
+ to ensure the environment is setup correctly to install COM objects, services, etc.
+ """,
+ )
+ parser.add_argument(
+ "-install",
+ default=False,
+ action="store_true",
+ help="Configure the Python environment correctly for pywin32.",
+ )
+ parser.add_argument(
+ "-remove",
+ default=False,
+ action="store_true",
+ help="Try and remove everything that was installed or copied.",
+ )
+ parser.add_argument(
+ "-wait",
+ type=int,
+ help="Wait for the specified process to terminate before starting.",
+ )
+ parser.add_argument(
+ "-silent",
+ default=False,
+ action="store_true",
+ help='Don\'t display the "Abort/Retry/Ignore" dialog for files in use.',
+ )
+ parser.add_argument(
+ "-quiet",
+ default=False,
+ action="store_true",
+ help="Don't display progress messages.",
+ )
+ parser.add_argument(
+ "-destination",
+ default=sysconfig.get_paths()["platlib"],
+ type=verify_destination,
+ help="Location of the PyWin32 installation",
+ )
+
+ args = parser.parse_args()
+
+ if not args.quiet:
+ print(f"Parsed arguments are: {args}")
+
+ if not args.install ^ args.remove:
+ parser.error("You need to either choose to -install or -remove!")
+
+ if args.wait is not None:
+ try:
+ os.waitpid(args.wait, 0)
+ except OSError:
+ # child already dead
+ pass
+
+ silent = args.silent
+ verbose = not args.quiet
+
+ if args.install:
+ install(args.destination)
+
+ if args.remove:
+ uninstall(args.destination)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.exe
new file mode 100644
index 00000000..79d5b8cc
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.py b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.py
new file mode 100644
index 00000000..345d6413
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/pywin32_testall.py
@@ -0,0 +1,120 @@
+"""A test runner for pywin32"""
+
+import os
+import site
+import subprocess
+import sys
+
+# locate the dirs based on where this script is - it may be either in the
+# source tree, or in an installed Python 'Scripts' tree.
+project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
+site_packages = [site.getusersitepackages()] + site.getsitepackages()
+
+failures = []
+
+
+# Run a test using subprocess and wait for the result.
+# If we get an returncode != 0, we know that there was an error, but we don't
+# abort immediately - we run as many tests as we can.
+def run_test(script, cmdline_extras):
+ dirname, scriptname = os.path.split(script)
+ # some tests prefer to be run from their directory.
+ cmd = [sys.executable, "-u", scriptname] + cmdline_extras
+ print("--- Running '%s' ---" % script)
+ sys.stdout.flush()
+ result = subprocess.run(cmd, check=False, cwd=dirname)
+ print(f"*** Test script '{script}' exited with {result.returncode}")
+ sys.stdout.flush()
+ if result.returncode:
+ failures.append(script)
+
+
+def find_and_run(possible_locations, extras):
+ for maybe in possible_locations:
+ if os.path.isfile(maybe):
+ run_test(maybe, extras)
+ break
+ else:
+ raise RuntimeError(
+ "Failed to locate a test script in one of %s" % possible_locations
+ )
+
+
+def main():
+ import argparse
+
+ code_directories = [project_root] + site_packages
+
+ parser = argparse.ArgumentParser(
+ description="A script to trigger tests in all subprojects of PyWin32."
+ )
+ parser.add_argument(
+ "-no-user-interaction",
+ default=False,
+ action="store_true",
+ help="(This is now the default - use `-user-interaction` to include them)",
+ )
+
+ parser.add_argument(
+ "-user-interaction",
+ action="store_true",
+ help="Include tests which require user interaction",
+ )
+
+ parser.add_argument(
+ "-skip-adodbapi",
+ default=False,
+ action="store_true",
+ help="Skip the adodbapi tests; useful for CI where there's no provider",
+ )
+
+ args, remains = parser.parse_known_args()
+
+ # win32, win32ui / Pythonwin
+
+ extras = []
+ if args.user_interaction:
+ extras.append("-user-interaction")
+ extras.extend(remains)
+ scripts = [
+ "win32/test/testall.py",
+ "Pythonwin/pywin/test/all.py",
+ ]
+ for script in scripts:
+ maybes = [os.path.join(directory, script) for directory in code_directories]
+ find_and_run(maybes, extras)
+
+ # win32com
+ maybes = [
+ os.path.join(directory, "win32com", "test", "testall.py")
+ for directory in [os.path.join(project_root, "com")] + site_packages
+ ]
+ extras = remains + ["1"] # only run "level 1" tests in CI
+ find_and_run(maybes, extras)
+
+ # adodbapi
+ if not args.skip_adodbapi:
+ maybes = [
+ os.path.join(directory, "adodbapi", "test", "adodbapitest.py")
+ for directory in code_directories
+ ]
+ find_and_run(maybes, remains)
+ # This script has a hard-coded sql server name in it, (and markh typically
+ # doesn't have a different server to test on) but there is now supposed to be a server out there on the Internet
+ # just to run these tests, so try it...
+ maybes = [
+ os.path.join(directory, "adodbapi", "test", "test_adodbapi_dbapi20.py")
+ for directory in code_directories
+ ]
+ find_and_run(maybes, remains)
+
+ if failures:
+ print("The following scripts failed")
+ for failure in failures:
+ print(">", failure)
+ sys.exit(1)
+ print("All tests passed \\o/")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html.exe
new file mode 100644
index 00000000..06a80782
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html4.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html4.exe
new file mode 100644
index 00000000..d25301e7
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html4.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html5.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html5.exe
new file mode 100644
index 00000000..c23c6d6c
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2html5.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2latex.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2latex.exe
new file mode 100644
index 00000000..aaf0b6fc
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2latex.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2man.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2man.exe
new file mode 100644
index 00000000..743ac8cc
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2man.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2odt.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2odt.exe
new file mode 100644
index 00000000..c3cb682d
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2odt.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2pseudoxml.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2pseudoxml.exe
new file mode 100644
index 00000000..f0697b3e
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2pseudoxml.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2s5.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2s5.exe
new file mode 100644
index 00000000..8ece440e
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2s5.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xetex.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xetex.exe
new file mode 100644
index 00000000..d540570d
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xetex.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xml.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xml.exe
new file mode 100644
index 00000000..1162dacd
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/rst2xml.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tiny-agents.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tiny-agents.exe
new file mode 100644
index 00000000..3f93c232
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tiny-agents.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tqdm.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tqdm.exe
new file mode 100644
index 00000000..c934d6f3
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/tqdm.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uv.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uv.exe
new file mode 100644
index 00000000..ab07d148
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uv.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvicorn.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvicorn.exe
new file mode 100644
index 00000000..a1406029
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvicorn.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvw.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvw.exe
new file mode 100644
index 00000000..b270dd44
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvw.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvx.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvx.exe
new file mode 100644
index 00000000..72ec2139
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/uvx.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/watchfiles.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/watchfiles.exe
new file mode 100644
index 00000000..0e98bc87
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/watchfiles.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/websockets.exe b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/websockets.exe
new file mode 100644
index 00000000..cfbc18dc
Binary files /dev/null and b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/Scripts/websockets.exe differ
diff --git a/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/pyvenv.cfg b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/pyvenv.cfg
new file mode 100644
index 00000000..30daa8da
--- /dev/null
+++ b/Co-creation-projects/EugeneChanQAQ-smart_fitness_planner/venv_fit/pyvenv.cfg
@@ -0,0 +1,5 @@
+home = C:\Users\admin\AppData\Local\Programs\Python\Python312
+include-system-site-packages = false
+version = 3.12.10
+executable = C:\Users\admin\AppData\Local\Programs\Python\Python312\python.exe
+command = C:\Users\admin\AppData\Local\Programs\Python\Python312\python.exe -m venv D:\pythonProject\smart_fitness_planner\venv_fit