Spaces:
Sleeping
Sleeping
File size: 6,933 Bytes
d27bdcb 19a6cbe 0ba59ec ac27b27 d27bdcb ac27b27 d27bdcb 0ba59ec d27bdcb 19a6cbe f8a47c9 19a6cbe ac27b27 d27bdcb ac27b27 d27bdcb 19a6cbe 0ba59ec d27bdcb 0ba59ec 19a6cbe d27bdcb f8a47c9 d27bdcb 19a6cbe 0ba59ec 19a6cbe d27bdcb 19a6cbe d27bdcb 19a6cbe d27bdcb 19a6cbe d27bdcb 0ba59ec d27bdcb 19a6cbe d27bdcb 5c82ae4 19a6cbe d27bdcb 5c82ae4 19a6cbe d27bdcb 19a6cbe d27bdcb 0ba59ec d27bdcb 19a6cbe d27bdcb 0ba59ec 5c82ae4 0ba59ec 5c82ae4 d27bdcb 5c82ae4 d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 5ef0fc4 ac27b27 5ef0fc4 ac27b27 5ef0fc4 ac27b27 5c82ae4 ac27b27 5ef0fc4 ac27b27 5ef0fc4 ac27b27 0ba59ec d27bdcb ac27b27 0ba59ec d27bdcb ac27b27 0ba59ec 5c82ae4 d27bdcb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
from fastapi import FastAPI, HTTPException, Form, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi_socketio import SocketManager
from typing import Optional
import pymongo
from bson.objectid import ObjectId
import redis
import json
from redis.exceptions import RedisError
from pydantic import BaseModel, validator
from pymongo.errors import ConnectionFailure
# Initialize FastAPI app
app = FastAPI()
socket_manager = SocketManager(app=app, cors_allowed_origins="*", mount_location="/socket.io")
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize Redis client
redis_client = redis.Redis(host='localhost', port=6379, db=0)
CACHE_EXPIRE_TIME = 300 # 5 minutes
# MongoDB connection
mongo_url = "mongodb+srv://ip6ofme:JL1S4hjMWRoko8AJ@cluster0.x0vo0.mongodb.net/"
client = pymongo.MongoClient(mongo_url)
db = client["test"]
pdf_collection = db["PdfDetails"]
voter_collection = db["Voters"]
# Kiểm tra kết nối MongoDB khi khởi động
try:
# The ismaster command is cheap and does not require auth.
client.admin.command('ismaster')
except ConnectionFailure:
print("Server not available")
raise
# Pydantic models for request validation
class VoterRegistration(BaseModel):
name: str
group: str
role: str
class VoteRequest(BaseModel):
voter_id: str
file_id: str
vote_count: Optional[int] = 1
class Config:
@validator('vote_count')
def validate_vote_count(cls, v):
if v <= 0:
raise ValueError('Vote count must be greater than 0')
return v
@app.post("/upload-files")
async def upload_file(
title: str = Form(...),
group: str = Form(...),
url: str = Form(...)
):
new_pdf = {
'title': title,
'group': group,
'url': url,
'votes': 0
}
result = pdf_collection.insert_one(new_pdf)
return {'status': 'ok', 'id': str(result.inserted_id)}
@app.get("/get-votes")
async def get_votes(file_id: str):
try:
file = pdf_collection.find_one({'_id': ObjectId(file_id)})
if not file:
raise HTTPException(status_code=404, detail="File not found")
return {'status': 'ok', 'votes': file.get('votes', 0)}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/get-files")
async def get_files():
try:
files = pdf_collection.find({})
file_list = [
{
'id': str(file['_id']),
'title': file['title'],
'group': file['group'],
'url': file['url'],
'votes': file.get('votes', 0)
}
for file in files
]
return {'status': 'ok', 'data': file_list}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/register-voter")
async def register_voter(voter: VoterRegistration):
# Xác định số lượng vote tối đa dựa vào role
max_votes = 10 if voter.role == 'judge' else 2
new_voter = {
'name': voter.name,
'group': voter.group,
'role': voter.role,
'number_of_votes': max_votes # Khởi tạo với số vote tối đa
}
result = voter_collection.insert_one(new_voter)
return {'status': 'ok', 'id': str(result.inserted_id)}
@app.post("/vote-by-voter")
async def vote_by_voter(vote_request: VoteRequest):
if vote_request.vote_count <= 0:
raise HTTPException(status_code=400, detail="Vote count must be greater than 0")
voter = voter_collection.find_one({'_id': ObjectId(vote_request.voter_id)})
if not voter:
raise HTTPException(status_code=404, detail="Voter not found")
# Kiểm tra số vote còn lại
remaining_votes = voter['number_of_votes'] # Số vote còn lại
if vote_request.vote_count > remaining_votes:
raise HTTPException(status_code=400, detail=f"Not enough votes remaining. You have {remaining_votes} votes left")
try:
# Cập nhật MongoDB - giảm số vote còn lại
voter_collection.update_one(
{'_id': ObjectId(vote_request.voter_id)},
{'$inc': {'number_of_votes': -vote_request.vote_count}} # Giảm số vote còn lại
)
pdf_collection.update_one(
{'_id': ObjectId(vote_request.file_id)},
{'$inc': {'votes': vote_request.vote_count}}
)
# Clear cache
redis_client.delete('all_files')
redis_client.delete(f'voter:{vote_request.voter_id}')
# Emit socket event
updated_file = pdf_collection.find_one({'_id': ObjectId(vote_request.file_id)})
await socket_manager.emit('vote_update', {
'file_id': vote_request.file_id,
'votes': updated_file.get('votes', 0)
})
return {'status': 'ok', 'message': f'Vote recorded successfully with {vote_request.vote_count} votes'}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/get-voter")
async def get_voter(id: str):
try:
# Check cache
try:
cached_voter = redis_client.get(f'voter:{id}')
if cached_voter:
return json.loads(cached_voter)
except RedisError as redis_err:
print(f"Redis error: {redis_err}")
pass
voter = voter_collection.find_one({'_id': ObjectId(id)})
if not voter:
raise HTTPException(status_code=404, detail="Voter not found")
voter_data = {
'status': 'ok',
'name': voter['name'],
'group': voter['group'],
'role': voter['role'],
'number_of_votes': voter['number_of_votes'] # Số này giờ là số vote còn lại
}
try:
redis_client.setex(f'voter:{id}', CACHE_EXPIRE_TIME, json.dumps(voter_data))
except RedisError as redis_err:
print(f"Redis caching error: {redis_err}")
pass
return voter_data
except Exception as e:
print(f"Error in get_voter: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@socket_manager.on('connect')
async def handle_connect(sid, environ):
print(f'Client connected: {sid}')
@socket_manager.on('disconnect')
async def handle_disconnect(sid):
print(f'Client disconnected: {sid}')
@app.get("/")
async def index():
return {'status': 'ok', 'message': 'Server is running'}
@app.on_event("shutdown")
async def shutdown_event():
# Close MongoDB connection
client.close()
# Close Redis connection
redis_client.close()
if _name_ == "_main_":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5000) |