Update mainweb.py

This commit is contained in:
2025-12-12 16:12:13 -05:00
parent 1946cc515a
commit a59c2c5919

View File

@@ -1,230 +1,321 @@
from flask import Flask, render_template, request, jsonify, session from flask import Flask, render_template, request, jsonify, session
import random import random
from datetime import datetime import json
import os
app = Flask(__name__) from datetime import datetime
app.secret_key = 'your_secret_key_here'
app = Flask(__name__)
# Game state management
game_state = {} # Leaderboard file path
LEADERBOARD_FILE = 'leaderboard.json'
def init_game(days):
"""Initialize a new game session""" # List of all companies - EASY TO ADD/REMOVE COMPANIES HERE
return { COMPANIES = [
'balance': 1000, {'id': 1, 'name': 'Kwik trip', 'key': 'kwiktrip'},
'kwiktripStockPrice': 100 + random.randint(-100, 100), {'id': 2, 'name': 'Apple computers', 'key': 'apple'},
'appleStockPrice': 100 + random.randint(-100, 100), {'id': 3, 'name': 'Microsoft', 'key': 'microsoft'},
'microsoftStockPrice': 100 + random.randint(-100, 100), {'id': 4, 'name': 'Walmart Super Store', 'key': 'walmart'},
'walmartStockPrice': 100 + random.randint(-100, 100), {'id': 5, 'name': 'Car company', 'key': 'car'},
'carStockPrice': 100 + random.randint(-100, 100), {'id': 6, 'name': 'Tesla', 'key': 'tesla'},
'kwiktrip': 0, {'id': 7, 'name': 'Amazon', 'key': 'amazon'},
'apple': 0, {'id': 8, 'name': 'Google', 'key': 'google'},
'microsoft': 0, {'id': 9, 'name': 'Netflix', 'key': 'netflix'},
'walmart': 0, {'id': 10, 'name': 'Steam', 'key': 'steam',},
'car': 0, {'id': 11, 'name': 'Nvidia', 'key': 'nvidia'}
'day': 1, ]
'daysleft': days,
'message': '' # Game state management
} game_state = {}
leaderboard = []
def calculate_index(state):
"""Calculate market index""" def load_leaderboard():
prices = [state['kwiktripStockPrice'], state['appleStockPrice'], """Load leaderboard from file"""
state['microsoftStockPrice'], state['walmartStockPrice'], global leaderboard
state['carStockPrice']] if os.path.exists(LEADERBOARD_FILE):
return sum(prices) / 5 try:
with open(LEADERBOARD_FILE, 'r') as f:
def get_stock_list(state): leaderboard = json.load(f)
"""Return list of stocks with prices""" except (json.JSONDecodeError, IOError):
return [ leaderboard = []
{'id': 1, 'name': 'Kwik trip', 'price': state['kwiktripStockPrice']}, else:
{'id': 2, 'name': 'Apple computers', 'price': state['appleStockPrice']}, leaderboard = []
{'id': 3, 'name': 'Microsoft', 'price': state['microsoftStockPrice']},
{'id': 4, 'name': 'Walmart Super Store', 'price': state['walmartStockPrice']}, def save_leaderboard():
{'id': 5, 'name': 'Car company', 'price': state['carStockPrice']} """Save leaderboard to file"""
] try:
with open(LEADERBOARD_FILE, 'w') as f:
def get_holdings(state): json.dump(leaderboard, f, indent=4)
"""Return user's stock holdings""" except IOError as e:
return [ print(f"Error saving leaderboard: {e}")
{'id': 1, 'name': 'Kwik trip', 'amount': state['kwiktrip']},
{'id': 2, 'name': 'Apple computers', 'amount': state['apple']}, def init_game(days):
{'id': 3, 'name': 'Microsoft', 'amount': state['microsoft']}, """Initialize a new game session"""
{'id': 4, 'name': 'Walmart Super Store', 'amount': state['walmart']}, # Generate random offsets for initial prices for each company
{'id': 5, 'name': 'Car company', 'amount': state['car']} price_offsets = {company['key']: random.randint(-100, 100) for company in COMPANIES}
]
# Build state with dynamic company prices and history
def get_game_state_data(): state = {
"""Get current game state data as dictionary""" 'balance': 1000,
if 'current' not in game_state: 'day': 1,
return None 'daysleft': days,
'leaderboardDays': days,
state = game_state['current'] 'message': '',
stocks = get_stock_list(state) 'priceHistory': {},
holdings = get_holdings(state) }
return { # Add stock prices and holdings for each company
'balance': state['balance'], for company in COMPANIES:
'day': state['day'], key = company['key']
'daysleft': state['daysleft'], offset = price_offsets[key]
'index': round(calculate_index(state), 2), # Ensure initial price is at least $1
'stocks': stocks, initial_price = max(1, 100 + offset)
'holdings': holdings, state[f'{key}StockPrice'] = initial_price
'message': state.get('message', '') state[key] = 0
} state['priceHistory'][key] = [initial_price]
@app.route('/') return state
def home():
"""Home page - ask for number of days""" def calculate_index(state):
return render_template('index.html') """Calculate market index"""
prices = [state[f"{company['key']}StockPrice"] for company in COMPANIES]
@app.route('/api/start', methods=['POST']) return sum(prices) / len(prices) if prices else 0
def start_game():
"""Initialize a new game""" def get_stock_list(state):
data = request.json """Return list of stocks with prices"""
days = int(data.get('days', 5)) return [
{'id': company['id'], 'name': company['name'], 'price': state[f"{company['key']}StockPrice"]}
state = init_game(days) for company in COMPANIES
game_state['current'] = state ]
return jsonify(get_game_state_data()) def get_holdings(state):
"""Return user's stock holdings"""
@app.route('/api/game-state', methods=['GET']) return [
def get_game_state(): {'id': company['id'], 'name': company['name'], 'amount': state[company['key']]}
"""Get current game state""" for company in COMPANIES
state_data = get_game_state_data() ]
if state_data is None:
return jsonify({'error': 'Game not started'}), 400 def get_game_state_data():
"""Get current game state data as dictionary"""
return jsonify(state_data) if 'current' not in game_state:
return None
@app.route('/api/buy', methods=['POST'])
def buy_stock(): state = game_state['current']
"""Buy stocks""" stocks = get_stock_list(state)
if 'current' not in game_state: holdings = get_holdings(state)
return jsonify({'error': 'Game not started'}), 400
return {
state = game_state['current'] 'balance': state['balance'],
data = request.json 'day': state['day'],
'daysleft': state['daysleft'],
try: 'index': round(calculate_index(state), 2),
stock_id = int(data['stock_id']) 'stocks': stocks,
amount = int(data['amount']) 'holdings': holdings,
'message': state.get('message', ''),
stocks = get_stock_list(state) 'priceHistory': state.get('priceHistory', {})
stock_price = stocks[stock_id - 1]['price'] }
total_cost = amount * stock_price
@app.route('/')
if state['balance'] < total_cost: def home():
state['message'] = f"Insufficient funds. Cost: ${total_cost}, Balance: ${state['balance']}" """Home page - ask for number of days"""
return jsonify({'error': state['message']}), 400 return render_template('index.html')
state['balance'] -= total_cost @app.route('/api/start', methods=['POST'])
def start_game():
stock_keys = ['kwiktrip', 'apple', 'microsoft', 'walmart', 'car'] """Initialize a new game"""
state[stock_keys[stock_id - 1]] += amount data = request.json
days = int(data.get('days', 5))
state['message'] = f"Successfully bought {amount} shares of {stocks[stock_id - 1]['name']} for ${total_cost}"
state = init_game(days)
return jsonify(get_game_state_data()) game_state['current'] = state
except (ValueError, IndexError, KeyError) as e:
return jsonify({'error': str(e)}), 400 return jsonify(get_game_state_data())
@app.route('/api/sell', methods=['POST']) @app.route('/api/game-state', methods=['GET'])
def sell_stock(): def get_game_state():
"""Sell stocks""" """Get current game state"""
if 'current' not in game_state: state_data = get_game_state_data()
return jsonify({'error': 'Game not started'}), 400 if state_data is None:
return jsonify({'error': 'Game not started'}), 400
state = game_state['current']
data = request.json return jsonify(state_data)
try: @app.route('/api/buy', methods=['POST'])
stock_id = int(data['stock_id']) def buy_stock():
amount = int(data['amount']) """Buy stocks"""
if 'current' not in game_state:
stocks = get_stock_list(state) return jsonify({'error': 'Game not started'}), 400
holdings = get_holdings(state)
state = game_state['current']
user_holdings = holdings[stock_id - 1]['amount'] data = request.json
if user_holdings < amount: try:
state['message'] = f"You don't own enough shares. You own: {user_holdings}" stock_id = int(data['stock_id'])
return jsonify({'error': state['message']}), 400 amount = int(data['amount'])
stock_price = stocks[stock_id - 1]['price'] stocks = get_stock_list(state)
total_payout = amount * stock_price stock_price = stocks[stock_id - 1]['price']
total_cost = amount * stock_price
state['balance'] += total_payout
if state['balance'] < total_cost:
stock_keys = ['kwiktrip', 'apple', 'microsoft', 'walmart', 'car'] state['message'] = f"Insufficient funds. Cost: ${total_cost}, Balance: ${state['balance']}"
state[stock_keys[stock_id - 1]] -= amount return jsonify({'error': state['message']}), 400
state['message'] = f"Successfully sold {amount} shares of {stocks[stock_id - 1]['name']} for ${total_payout}" state['balance'] -= total_cost
return jsonify(get_game_state_data()) # Use dynamic COMPANIES list instead of hardcoded array
except (ValueError, IndexError, KeyError) as e: stock_key = COMPANIES[stock_id - 1]['key']
return jsonify({'error': str(e)}), 400 state[stock_key] += amount
@app.route('/api/next-day', methods=['POST']) state['message'] = f"Successfully bought {amount} shares of {stocks[stock_id - 1]['name']} for ${total_cost}"
def next_day():
"""Progress to next day""" return jsonify(get_game_state_data())
if 'current' not in game_state: except (ValueError, IndexError, KeyError) as e:
return jsonify({'error': 'Game not started'}), 400 return jsonify({'error': str(e)}), 400
state = game_state['current'] @app.route('/api/sell', methods=['POST'])
def sell_stock():
if state['daysleft'] <= 0: """Sell stocks"""
return jsonify({'error': 'Game over!', 'game_over': True}), 400 if 'current' not in game_state:
return jsonify({'error': 'Game not started'}), 400
state['day'] += 1
state['daysleft'] -= 1 state = game_state['current']
data = request.json
# Update stock prices
state['kwiktripStockPrice'] = abs(state['kwiktripStockPrice'] + random.randint(-100, 100)) try:
state['appleStockPrice'] = abs(state['appleStockPrice'] + random.randint(-100, 100)) stock_id = int(data['stock_id'])
state['microsoftStockPrice'] = abs(state['microsoftStockPrice'] + random.randint(-100, 100)) amount = int(data['amount'])
state['walmartStockPrice'] = abs(state['walmartStockPrice'] + random.randint(-100, 100))
state['carStockPrice'] = abs(state['carStockPrice'] + random.randint(-100, 100)) stocks = get_stock_list(state)
holdings = get_holdings(state)
# Market crash chance
if random.randint(0, 1000) == 555: user_holdings = holdings[stock_id - 1]['amount']
state['kwiktripStockPrice'] = 10
state['appleStockPrice'] = 10 if user_holdings < amount:
state['microsoftStockPrice'] = 10 state['message'] = f"You don't own enough shares. You own: {user_holdings}"
state['walmartStockPrice'] = 10 return jsonify({'error': state['message']}), 400
state['carStockPrice'] = 10
state['message'] = "Market crash! All stocks dropped to $10" stock_price = stocks[stock_id - 1]['price']
else: total_payout = amount * stock_price
state['message'] = f"Moved to day {state['day']}"
state['balance'] += total_payout
return jsonify(get_game_state_data())
# Use dynamic COMPANIES list instead of hardcoded array
@app.route('/api/end-game', methods=['GET']) stock_key = COMPANIES[stock_id - 1]['key']
def end_game(): state[stock_key] -= amount
"""Get end game statistics"""
if 'current' not in game_state: state['message'] = f"Successfully sold {amount} shares of {stocks[stock_id - 1]['name']} for ${total_payout}"
return jsonify({'error': 'Game not started'}), 400
return jsonify(get_game_state_data())
state = game_state['current'] except (ValueError, IndexError, KeyError) as e:
stocks = get_stock_list(state) return jsonify({'error': str(e)}), 400
total_net_worth = state['balance'] @app.route('/api/next-day', methods=['POST'])
holdings = get_holdings(state) def next_day():
"""Progress to next day"""
for i, holding in enumerate(holdings): if 'current' not in game_state:
total_net_worth += holding['amount'] * stocks[i]['price'] return jsonify({'error': 'Game not started'}), 400
profit = state['balance'] - 1000 state = game_state['current']
return jsonify({ if state['daysleft'] <= 0:
'starting_balance': 1000, return jsonify({'error': 'Game over!', 'game_over': True}), 400
'ending_balance': state['balance'],
'total_net_worth': round(total_net_worth, 2), state['day'] += 1
'profit': profit, state['daysleft'] -= 1
'holdings': holdings,
'stocks': stocks # Update stock prices dynamically for all companies
}) for company in COMPANIES:
key = company['key']
if __name__ == '__main__': price_key = f"{key}StockPrice"
app.run(debug=True) new_price = state[price_key] + random.randint(-100, 100)
# Ensure price is at least $1
state[price_key] = max(1, new_price)
state['priceHistory'][key].append(state[price_key])
# Market crash chance
if random.randint(0, 1000) == 555:
# Market crash - set all prices to $1 minimum
for company in COMPANIES:
key = company['key']
crash_price = max(1, int(state[f"{key}StockPrice"] * 0.2)) # Drop to 20% of current price, but no lower than $1
state[f"{key}StockPrice"] = crash_price
state['priceHistory'][key][-1] = crash_price
state['message'] = "Market crash! All stocks dropped significantly!"
else:
state['message'] = f"Moved to day {state['day']}"
return jsonify(get_game_state_data())
@app.route('/api/end-game', methods=['GET'])
def end_game():
"""Get end game statistics"""
if 'current' not in game_state:
return jsonify({'error': 'Game not started'}), 400
state = game_state['current']
stocks = get_stock_list(state)
total_net_worth = state['balance']
holdings = get_holdings(state)
for i, holding in enumerate(holdings):
total_net_worth += holding['amount'] * stocks[i]['price']
profit = state['balance'] - 1000
return jsonify({
'starting_balance': 1000,
'ending_balance': state['balance'],
'total_net_worth': round(total_net_worth, 2),
'profit': profit,
'holdings': holdings,
'stocks': stocks
})
@app.route('/api/save-score', methods=['POST'])
def save_score():
"""Save game score to leaderboard"""
if 'current' not in game_state:
return jsonify({'error': 'Game not started'}), 400
data = request.json
player_name = data.get('name', 'Anonymous')
state = game_state['current']
stocks = get_stock_list(state)
total_net_worth = state['balance']
holdings = get_holdings(state)
for i, holding in enumerate(holdings):
total_net_worth += holding['amount'] * stocks[i]['price']
profit = state['balance'] - 1000
score_entry = {
'name': player_name,
'profit': profit,
'net_worth': round(total_net_worth, 2),
'final_balance': state['balance'],
'leaderboardDays': state['leaderboardDays'],
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
leaderboard.append(score_entry)
leaderboard.sort(key=lambda x: x['profit'], reverse=True)
# Save leaderboard to file
save_leaderboard()
return jsonify({'success': True, 'rank': leaderboard.index(score_entry) + 1})
@app.route('/api/leaderboard', methods=['GET'])
def get_leaderboard():
"""Get leaderboard scores"""
return jsonify({'scores': leaderboard[:10]})
# Load leaderboard from file at startup
load_leaderboard()
if __name__ == '__main__':
app.run(debug=False)