t
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# 接收构建参数 BASE_IMAGE,由 docker_deply.sh 传入
|
# 接收构建参数 BASE_IMAGE,由 docker_deply.sh 传入
|
||||||
ARG BASE_IMAGE=python:3.9-slim
|
ARG BASE_IMAGE=python:3.9-slim
|
||||||
FROM ${BASE_IMAGE}
|
FROM ${BASE_IMAGE}
|
||||||
|
# FROM docker.m.daocloud.io/python:3.9-slim
|
||||||
|
|
||||||
# 设置工作目录
|
# 设置工作目录
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -37,7 +37,9 @@ PLATFORM="linux/amd64" # 默认架构
|
|||||||
ARCH_SUFFIX="" # 架构后缀,用于区分不同架构的tar文件
|
ARCH_SUFFIX="" # 架构后缀,用于区分不同架构的tar文件
|
||||||
# 默认使用华为云源 (AMD64速度快)
|
# 默认使用华为云源 (AMD64速度快)
|
||||||
BASE_IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/python:3.9-slim"
|
BASE_IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/python:3.9-slim"
|
||||||
|
if [ "$PLATFORM" = "linux/arm64" ]; then
|
||||||
|
BASE_IMAGE="docker.m.daocloud.io/python:3.9-slim"
|
||||||
|
fi
|
||||||
# 颜色输出
|
# 颜色输出
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
|
|||||||
69
main.py
69
main.py
@@ -9,6 +9,7 @@ from typing import Optional, List, Dict
|
|||||||
import random
|
import random
|
||||||
import uuid
|
import uuid
|
||||||
import os
|
import os
|
||||||
|
import difflib
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -54,36 +55,42 @@ def assign_seat(cur, user_industry: str) -> str:
|
|||||||
"""
|
"""
|
||||||
Allocate a seat based on:
|
Allocate a seat based on:
|
||||||
1. Even distribution (11 tables, max 12 per table)
|
1. Even distribution (11 tables, max 12 per table)
|
||||||
|
- Prioritize filling empty tables first (min count)
|
||||||
|
- If counts are equal, fill sequentially (Table 1 before Table 2)
|
||||||
2. Mix industries (try to put user in a table where their industry is least represented)
|
2. Mix industries (try to put user in a table where their industry is least represented)
|
||||||
|
- Uses natural language similarity to judge industry overlap
|
||||||
"""
|
"""
|
||||||
TOTAL_TABLES = 11
|
TOTAL_TABLES = 11
|
||||||
MAX_PER_TABLE = 12
|
MAX_PER_TABLE = 12
|
||||||
|
|
||||||
# Initialize table stats
|
# Initialize table stats
|
||||||
# tables = { 1: {'count': 0, 'industries': []}, ... }
|
|
||||||
tables = {i: {'count': 0, 'industries': []} for i in range(1, TOTAL_TABLES + 1)}
|
tables = {i: {'count': 0, 'industries': []} for i in range(1, TOTAL_TABLES + 1)}
|
||||||
|
|
||||||
# Fetch current seating status
|
# Fetch current seating status
|
||||||
# We join checkin_info with gsdh_data to get industries of people ALREADY SEATED
|
# Uses aggregation for efficiency as requested
|
||||||
|
# We use array_agg to collect industries for the diversity check in one query
|
||||||
query = """
|
query = """
|
||||||
SELECT ci.location, gd.industry_company
|
SELECT ci.location, COUNT(ci.gsdh_id), array_agg(gd.industry_company)
|
||||||
FROM checkin_info ci
|
FROM checkin_info ci
|
||||||
JOIN gsdh_data gd ON ci.gsdh_id = gd.new_id
|
LEFT JOIN gsdh_data gd ON ci.gsdh_id = gd.new_id
|
||||||
WHERE ci.location IS NOT NULL AND ci.location LIKE '第%桌'
|
WHERE ci.location IS NOT NULL AND ci.location LIKE '第%桌'
|
||||||
|
GROUP BY ci.location
|
||||||
"""
|
"""
|
||||||
cur.execute(query)
|
cur.execute(query)
|
||||||
rows = cur.fetchall()
|
rows = cur.fetchall()
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
loc = row[0] # e.g. "第1桌"
|
loc = row[0]
|
||||||
ind = row[1]
|
count = row[1]
|
||||||
|
industries = row[2] if row[2] else []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Extract table number
|
# Extract table number
|
||||||
table_num = int(loc.replace("第", "").replace("桌", ""))
|
table_num = int(loc.replace("第", "").replace("桌", ""))
|
||||||
if 1 <= table_num <= TOTAL_TABLES:
|
if 1 <= table_num <= TOTAL_TABLES:
|
||||||
tables[table_num]['count'] += 1
|
tables[table_num]['count'] = count
|
||||||
if ind:
|
# Filter out None values from industries
|
||||||
tables[table_num]['industries'].append(ind)
|
tables[table_num]['industries'] = [ind for ind in industries if ind]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -93,33 +100,39 @@ def assign_seat(cur, user_industry: str) -> str:
|
|||||||
if not available_tables:
|
if not available_tables:
|
||||||
return "自由席" # Fallback if all full
|
return "自由席" # Fallback if all full
|
||||||
|
|
||||||
# Strategy 1: Find tables with Minimum Count (Even Distribution)
|
# Strategy 1: Find tables with Minimum Count
|
||||||
|
# This automatically handles "Prioritize filling TOTAL_TABLES" because empty tables have count 0
|
||||||
min_count = min(t[1]['count'] for t in available_tables)
|
min_count = min(t[1]['count'] for t in available_tables)
|
||||||
candidates_step1 = [t for t in available_tables if t[1]['count'] == min_count]
|
candidates = [t for t in available_tables if t[1]['count'] == min_count]
|
||||||
|
|
||||||
# Strategy 2: Among candidates, find best for diversity
|
# Sort by table number to ensure sequential filling if counts are equal (Requirement: 顺序分配)
|
||||||
# We want a table where user_industry is NOT present, or present least often
|
candidates.sort(key=lambda x: x[0])
|
||||||
best_table = None
|
|
||||||
|
|
||||||
# If user has no industry info, just pick random from candidates
|
# Strategy 2: Optimize for Industry Diversity
|
||||||
if not user_industry:
|
if not user_industry:
|
||||||
best_table = random.choice(candidates_step1)[0]
|
# If no industry info, just pick the first one (Sequential)
|
||||||
|
best_table = candidates[0][0]
|
||||||
else:
|
else:
|
||||||
# Score candidates: lower score is better (score = count of this industry in that table)
|
# Calculate similarity scores
|
||||||
|
# Score = sum of similarity with existing users
|
||||||
|
# Lower score is better (more unique)
|
||||||
scored_candidates = []
|
scored_candidates = []
|
||||||
for table_id, stats in candidates_step1:
|
|
||||||
# Simple fuzzy check: count how many times user_industry appears in stats['industries']
|
|
||||||
# We use simple string containment
|
|
||||||
industry_count = sum(1 for existing_ind in stats['industries'] if existing_ind and user_industry in existing_ind)
|
|
||||||
scored_candidates.append((table_id, industry_count))
|
|
||||||
|
|
||||||
# Sort by industry count (asc)
|
for table_id, stats in candidates:
|
||||||
scored_candidates.sort(key=lambda x: x[1])
|
total_similarity = 0.0
|
||||||
|
for existing_ind in stats['industries']:
|
||||||
|
if existing_ind:
|
||||||
|
# Use difflib for fuzzy matching (0.0 to 1.0)
|
||||||
|
# This helps understand "Natural Language" industries better than exact match
|
||||||
|
sim = difflib.SequenceMatcher(None, user_industry, existing_ind).ratio()
|
||||||
|
total_similarity += sim
|
||||||
|
|
||||||
# Pick the one with least collision
|
scored_candidates.append((table_id, total_similarity))
|
||||||
min_collision = scored_candidates[0][1]
|
|
||||||
final_candidates = [x[0] for x in scored_candidates if x[1] == min_collision]
|
# Sort by similarity score (asc), then by table_id (asc)
|
||||||
best_table = random.choice(final_candidates)
|
scored_candidates.sort(key=lambda x: (x[1], x[0]))
|
||||||
|
|
||||||
|
best_table = scored_candidates[0][0]
|
||||||
|
|
||||||
return f"第{best_table}桌"
|
return f"第{best_table}桌"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user