From ad84c4694ad98e3002e82db4b824c03c7e0b24de Mon Sep 17 00:00:00 2001 From: darthfelipe21 Date: Thu, 26 Jun 2025 12:16:28 -0400 Subject: [PATCH] Implement elevator data collection system with CRUD API, tests and indices --- .DS_Store | Bin 0 -> 6148 bytes .idea/.gitignore | 3 + .idea/devtest.iml | 10 + .idea/inspectionProfiles/Project_Default.xml | 10 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 10 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + chatgpt/.DS_Store | Bin 0 -> 6148 bytes .../app_tests.cpython-312-pytest-6.2.5.pyc | Bin 0 -> 29874 bytes chatgpt/__pycache__/main.cpython-312.pyc | Bin 0 -> 12373 bytes chatgpt/app_tests.py | 175 ++++++++++++++++- chatgpt/db.sql | 23 ++- chatgpt/instance/.DS_Store | Bin 0 -> 6148 bytes chatgpt/instance/elevator.db | Bin 0 -> 28672 bytes chatgpt/main.py | 181 ++++++++++++++++-- chatgpt/requirements.txt | 8 +- 17 files changed, 416 insertions(+), 24 deletions(-) create mode 100644 .DS_Store create mode 100644 .idea/.gitignore create mode 100644 .idea/devtest.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 chatgpt/.DS_Store create mode 100644 chatgpt/__pycache__/app_tests.cpython-312-pytest-6.2.5.pyc create mode 100644 chatgpt/__pycache__/main.cpython-312.pyc create mode 100644 chatgpt/instance/.DS_Store create mode 100644 chatgpt/instance/elevator.db diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b4a361ef2a9834b55b01fa92b7e6df722d706203 GIT binary patch literal 6148 zcmeHKJ8nWT5S&erfLj3PX~u+0f-ZZ!#Iy# zg4jGj?1e)jBQ#4YF{xH9h9#ZxR(ZW}NK87cnh&d+tvVEo+j)MAbXZT+C}^3Wq4i#3;vHcsYKI cq|9qR=YB675`)fo(24pPa9w0l;MNM90Fg}h($ literal 0 HcmV?d00001 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/devtest.iml b/.idea/devtest.iml new file mode 100644 index 0000000..6ecad54 --- /dev/null +++ b/.idea/devtest.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..146ab09 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..784420d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..901b03a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chatgpt/.DS_Store b/chatgpt/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..931ec6586914c8072f62320b054560c4a957369d GIT binary patch literal 6148 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 literal 0 HcmV?d00001 diff --git a/chatgpt/__pycache__/main.cpython-312.pyc b/chatgpt/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26390a706292be5d0a2da503e143d21eb8b828ea GIT binary patch literal 12373 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 V{#m=`KWo?jXOif-Daw0U`UQ!Bq22%h literal 0 HcmV?d00001 diff --git a/chatgpt/main.py b/chatgpt/main.py index 7f97d98..1c7679b 100644 --- a/chatgpt/main.py +++ b/chatgpt/main.py @@ -1,43 +1,194 @@ +# Import necessary libraries from flask import Flask, request, jsonify from flask_sqlalchemy import SQLAlchemy from datetime import datetime +from sqlalchemy.sql import text +# Set up Flask app and connect to SQLite database app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///elevator.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Turn off warnings for SQLAlchemy db = SQLAlchemy(app) +# Class model for elevator demands class ElevatorDemand(db.Model): + __tablename__ = 'elevator_demands' # Set table name and ForeignKey reference id = db.Column(db.Integer, primary_key=True) - timestamp = db.Column(db.DateTime, default=datetime.utcnow) - floor = db.Column(db.Integer, nullable=False) + timestamp = db.Column(db.DateTime, default=datetime.now()) # Store when the demand was made + floor = db.Column(db.Integer, nullable=False) # Floor number, can be positive or negative + day_of_week = db.Column(db.Integer, nullable=False) # Day of the week (0-6, Mon-Sun) + hour_of_day = db.Column(db.Integer, nullable=False) # Hour of the day (0-23) + def __init__(self, floor): + self.floor = floor + self.day_of_week = datetime.now().weekday() # Save the current day of the week + self.hour_of_day = datetime.now().hour # Save the current hour + # Convert demand to a dictionary for JSON response + def to_dict(self): + return { + 'id': self.id, + 'timestamp': self.timestamp.isoformat(), + 'floor': self.floor, + 'day_of_week': self.day_of_week, + 'hour_of_day': self.hour_of_day + } + + +# Class model for elevator states class ElevatorState(db.Model): + __tablename__ = 'elevator_states' # Set table name id = db.Column(db.Integer, primary_key=True) - timestamp = db.Column(db.DateTime, default=datetime.utcnow) - floor = db.Column(db.Integer, nullable=False) - vacant = db.Column(db.Boolean, nullable=False) + timestamp = db.Column(db.DateTime, default=datetime.now()) # Store when the state was recorded + floor = db.Column(db.Integer, nullable=False) # Current floor of the elevator + vacant = db.Column(db.Boolean, nullable=False) # True if elevator is empty, False if not + day_of_week = db.Column(db.Integer, nullable=False) # Day of the week (0-6) + hour_of_day = db.Column(db.Integer, nullable=False) # Hour of the day (0-23) + # Link to a demand if the elevator is not vacant + demand_id = db.Column(db.Integer, db.ForeignKey('elevator_demands.id'), nullable=True) + # Set up relationship to access demand data easily + demand = db.relationship('ElevatorDemand', backref=db.backref('states', lazy=True)) + + def __init__(self, floor, vacant, demand_id=None): + self.floor = floor + self.vacant = vacant + self.demand_id = demand_id + self.day_of_week = datetime.now().weekday() # Save current day + self.hour_of_day = datetime.now().hour # Save current hour + # Convert state to a dictionary for JSON response + def to_dict(self): + return { + 'id': self.id, + 'timestamp': self.timestamp.isoformat(), + 'floor': self.floor, + 'vacant': self.vacant, + 'day_of_week': self.day_of_week, + 'hour_of_day': self.hour_of_day, + 'demand_id': self.demand_id + } + +# Create a demand when someone calls the elevator @app.route('/demand', methods=['POST']) def create_demand(): data = request.get_json() - new_demand = ElevatorDemand(floor=data['floor']) - db.session.add(new_demand) - db.session.commit() - return jsonify({'message': 'Demand created'}), 201 + if not isinstance(data.get('floor'), int): + return jsonify({'error': 'Floor must be an integer'}), 400 # Check if floor is valid + new_demand = ElevatorDemand(floor=data['floor']) # Create new demand + db.session.add(new_demand) # Add to database + db.session.commit() # Save changes + # Return the created demand with its details + return jsonify({'message': 'Demand created', 'demand': new_demand.to_dict()}), 201 + + +# Get a specific demand by ID +@app.route('/demand/', methods=['GET']) +def get_demand(id): + demand = ElevatorDemand.query.get_or_404(id) # Find demand or return 404 + return jsonify(demand.to_dict()), 200 # Return demand details + + +# Get all demands +@app.route('/demands', methods=['GET']) +def get_all_demands(): + demands = ElevatorDemand.query.all() # Grab all demands from the database + return jsonify([demand.to_dict() for demand in demands]), 200 # Return list of demands + + +# Update an existing demand +@app.route('/demand/', methods=['PUT']) +def update_demand(id): + demand = ElevatorDemand.query.get_or_404(id) # Find demand or 404 + data = request.get_json() + if not isinstance(data.get('floor'), int): + return jsonify({'error': 'Floor must be an integer'}), 400 # Validate floor + demand.floor = data['floor'] # Update floor + db.session.commit() # Save changes + return jsonify({'message': 'Demand updated', 'demand': demand.to_dict()}), 200 # Return updated demand +# Delete a demand +@app.route('/demand/', methods=['DELETE']) +def delete_demand(id): + demand = ElevatorDemand.query.get_or_404(id) # Find demand or 404 + db.session.delete(demand) # Remove it + db.session.commit() # Save changes + return jsonify({'message': 'Demand deleted'}), 200 # Confirm deletion + + +# Create a new elevator state @app.route('/state', methods=['POST']) def create_state(): data = request.get_json() - new_state = ElevatorState(floor=data['floor'], vacant=data['vacant']) - db.session.add(new_state) - db.session.commit() - return jsonify({'message': 'State created'}), 201 + if not isinstance(data.get('floor'), int): + return jsonify({'error': 'Floor must be an integer'}), 400 # Check floor is an integer + if not isinstance(data.get('vacant'), bool): + return jsonify({'error': 'Vacant must be a boolean'}), 400 # Check vacant is boolean + demand_id = data.get('demand_id') + if not data['vacant'] and demand_id is None: + return jsonify({'error': 'Non-vacant state requires a valid demand_id'}), 400 # Check non-vacant states + if demand_id is not None and ElevatorDemand.query.get(demand_id) is None: + return jsonify({'error': 'Invalid demand_id'}), 400 # Validate demand_id + new_state = ElevatorState(floor=data['floor'], vacant=data['vacant'], demand_id=demand_id) # Create new state + db.session.add(new_state) # Add to database + db.session.commit() # Save changes + return jsonify({'message': 'State created', 'state': new_state.to_dict()}), 201 # Return created state + + +# Get a specific state by its ID +@app.route('/state/', methods=['GET']) +def get_state(id): + state = ElevatorState.query.get_or_404(id) # Find state or 404 + return jsonify(state.to_dict()), 200 # Return state details + + +# Get all states +@app.route('/states', methods=['GET']) +def get_all_states(): + states = ElevatorState.query.all() # Grab all states + return jsonify([state.to_dict() for state in states]), 200 # Return list of states + + +# Update an existing state +@app.route('/state/', methods=['PUT']) +def update_state(id): + state = ElevatorState.query.get_or_404(id) # Find state or 404 + data = request.get_json() + if not isinstance(data.get('floor'), int): + return jsonify({'error': 'Floor must be an integer'}), 400 # Validate floor + if not isinstance(data.get('vacant'), bool): + return jsonify({'error': 'Vacant must be a boolean'}), 400 # Validate vacant + demand_id = data.get('demand_id') + if not data['vacant'] and demand_id is None: + return jsonify({'error': 'Non-vacant state requires a valid demand_id'}), 400 # Check non-vacant states + if demand_id is not None and ElevatorDemand.query.get(demand_id) is None: + return jsonify({'error': 'Invalid demand_id'}), 400 # Validate demand_id + state.floor = data['floor'] # Update floor + state.vacant = data['vacant'] # Update vacant status + state.demand_id = demand_id # Update demand_id + db.session.commit() # Save changes + return jsonify({'message': 'State updated', 'state': state.to_dict()}), 200 # Return updated state + + +# Delete a state +@app.route('/state/', methods=['DELETE']) +def delete_state(id): + state = ElevatorState.query.get_or_404(id) # Find state or 404 + db.session.delete(state) # Remove it + db.session.commit() # Save changes + return jsonify({'message': 'State deleted'}), 200 # Confirm deletion +# Start the app and create database tables if __name__ == '__main__': - db.create_all() - app.run(debug=True) + with app.app_context(): + db.create_all() # Set up the database tables + with db.engine.connect() as connection: + connection.execute(text('CREATE INDEX IF NOT EXISTS idx_demands_timestamp ON elevator_demands(timestamp)')) + connection.execute(text('CREATE INDEX IF NOT EXISTS idx_states_timestamp ON elevator_states(timestamp)')) + connection.execute(text('CREATE INDEX IF NOT EXISTS idx_demands_floor ON elevator_demands(floor)')) + connection.execute(text('CREATE INDEX IF NOT EXISTS idx_states_floor ON elevator_states(floor)')) + print("Database tables created!") + app.run(debug=True) # Run the app in debug mode diff --git a/chatgpt/requirements.txt b/chatgpt/requirements.txt index 14d1bb0..f6f7710 100644 --- a/chatgpt/requirements.txt +++ b/chatgpt/requirements.txt @@ -1,4 +1,4 @@ -Flask==2.0.2 -Flask-SQLAlchemy==2.5.1 -pytest==6.2.5 -pytest-flask==1.2.0 +Flask +Flask-SQLAlchemy +pytest +pytest-flask