| """ |
| StadiumIQ Database Models |
| FIFA World Cup 2026 |
| """ |
|
|
| from datetime import datetime |
| from flask_sqlalchemy import SQLAlchemy |
|
|
| db = SQLAlchemy() |
|
|
|
|
| class Stadium(db.Model): |
| """FIFA World Cup 2026 venue.""" |
| __tablename__ = 'stadiums' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| name = db.Column(db.String(200), nullable=False) |
| city = db.Column(db.String(100), nullable=False) |
| country = db.Column(db.String(50), nullable=False) |
| capacity = db.Column(db.Integer, nullable=False) |
| latitude = db.Column(db.Float, nullable=False) |
| longitude = db.Column(db.Float, nullable=False) |
| image_url = db.Column(db.String(500), default='') |
| description = db.Column(db.Text, default='') |
|
|
| |
| matches = db.relationship('Match', backref='stadium', lazy=True) |
| pois = db.relationship('PointOfInterest', backref='stadium', lazy=True) |
| crowd_snapshots = db.relationship('CrowdSnapshot', backref='stadium', lazy=True) |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'name': self.name, |
| 'city': self.city, |
| 'country': self.country, |
| 'capacity': self.capacity, |
| 'latitude': self.latitude, |
| 'longitude': self.longitude, |
| 'image_url': self.image_url, |
| 'description': self.description, |
| } |
|
|
|
|
| class Match(db.Model): |
| """FIFA World Cup 2026 match.""" |
| __tablename__ = 'matches' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| team_a = db.Column(db.String(100), nullable=False) |
| team_b = db.Column(db.String(100), nullable=False) |
| team_a_flag = db.Column(db.String(10), default='🏳️') |
| team_b_flag = db.Column(db.String(10), default='🏳️') |
| match_date = db.Column(db.DateTime, nullable=False) |
| stadium_id = db.Column(db.Integer, db.ForeignKey('stadiums.id'), nullable=False) |
| stage = db.Column(db.String(50), nullable=False) |
| group_name = db.Column(db.String(20), default='') |
| score_a = db.Column(db.Integer, default=None, nullable=True) |
| score_b = db.Column(db.Integer, default=None, nullable=True) |
| status = db.Column(db.String(20), default='scheduled') |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'team_a': self.team_a, |
| 'team_b': self.team_b, |
| 'team_a_flag': self.team_a_flag, |
| 'team_b_flag': self.team_b_flag, |
| 'match_date': self.match_date.isoformat(), |
| 'stadium_id': self.stadium_id, |
| 'stadium_name': self.stadium.name if self.stadium else '', |
| 'stage': self.stage, |
| 'group_name': self.group_name, |
| 'score_a': self.score_a, |
| 'score_b': self.score_b, |
| 'status': self.status, |
| } |
|
|
|
|
| class PointOfInterest(db.Model): |
| """Point of interest within a stadium.""" |
| __tablename__ = 'points_of_interest' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| stadium_id = db.Column(db.Integer, db.ForeignKey('stadiums.id'), nullable=False) |
| name = db.Column(db.String(200), nullable=False) |
| category = db.Column(db.String(50), nullable=False) |
| description = db.Column(db.Text, default='') |
| latitude = db.Column(db.Float, nullable=False) |
| longitude = db.Column(db.Float, nullable=False) |
| floor = db.Column(db.String(20), default='Ground') |
| is_accessible = db.Column(db.Boolean, default=True) |
| icon = db.Column(db.String(50), default='map-pin') |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'stadium_id': self.stadium_id, |
| 'name': self.name, |
| 'category': self.category, |
| 'description': self.description, |
| 'latitude': self.latitude, |
| 'longitude': self.longitude, |
| 'floor': self.floor, |
| 'is_accessible': self.is_accessible, |
| 'icon': self.icon, |
| } |
|
|
|
|
| class CrowdSnapshot(db.Model): |
| """Real-time crowd density snapshot.""" |
| __tablename__ = 'crowd_snapshots' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| stadium_id = db.Column(db.Integer, db.ForeignKey('stadiums.id'), nullable=False) |
| zone = db.Column(db.String(50), nullable=False) |
| density_level = db.Column(db.Integer, nullable=False) |
| people_count = db.Column(db.Integer, default=0) |
| timestamp = db.Column(db.DateTime, default=datetime.utcnow) |
| alert_level = db.Column(db.String(20), default='normal') |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'stadium_id': self.stadium_id, |
| 'zone': self.zone, |
| 'density_level': self.density_level, |
| 'people_count': self.people_count, |
| 'timestamp': self.timestamp.isoformat(), |
| 'alert_level': self.alert_level, |
| } |
|
|
|
|
| class ChatHistory(db.Model): |
| """AI chatbot conversation history.""" |
| __tablename__ = 'chat_history' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| session_id = db.Column(db.String(100), nullable=False) |
| user_message = db.Column(db.Text, nullable=False) |
| ai_response = db.Column(db.Text, nullable=False) |
| language = db.Column(db.String(10), default='en') |
| timestamp = db.Column(db.DateTime, default=datetime.utcnow) |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'session_id': self.session_id, |
| 'user_message': self.user_message, |
| 'ai_response': self.ai_response, |
| 'language': self.language, |
| 'timestamp': self.timestamp.isoformat(), |
| } |
|
|
|
|
| class SustainabilityAction(db.Model): |
| """User sustainability action log.""" |
| __tablename__ = 'sustainability_actions' |
|
|
| id = db.Column(db.Integer, primary_key=True) |
| session_id = db.Column(db.String(100), nullable=False) |
| action_type = db.Column(db.String(100), nullable=False) |
| description = db.Column(db.Text, default='') |
| impact_score = db.Column(db.Float, default=0.0) |
| carbon_saved_kg = db.Column(db.Float, default=0.0) |
| timestamp = db.Column(db.DateTime, default=datetime.utcnow) |
|
|
| def to_dict(self): |
| return { |
| 'id': self.id, |
| 'session_id': self.session_id, |
| 'action_type': self.action_type, |
| 'description': self.description, |
| 'impact_score': self.impact_score, |
| 'carbon_saved_kg': self.carbon_saved_kg, |
| 'timestamp': self.timestamp.isoformat(), |
| } |
|
|