2.0 Roto
1.0 funcional
<!DOCTYPE html>
<html>
<head>
    <title>Transatlantic Simulator</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Parisienne&display=swap');
        body {
            font-family: 'Parisienne', cursive;
            background-color: darkblue;
            color: gold;
        }
        table {
            border-collapse: collapse;
            width: 100%;
        }
        table, th, td {
            border: 1px solid lightblue;
            padding: 8px;
        }
        th {
            text-align: left;
            background-color: #f2f2f2;
        }
        tr:hover {
            background-color: #f5f5f5;
        }
    </style>
</head>
<body>
    <h1>Transatlantic Simulator</h1>
    <p>Date: <span id="date">January 1880</span></p>
    <p>Money: <span id="money">10M</span></p>
    <button id="nextMonthButton">Next month</button>
    <button id="resetButton">Reset game</button>
    <img id="yearImage" src="">
    <p>Start with 10M of money. You can build transatlantic ships and choose the length and details.</p>
    <p>Base cost: The cost of a ship depends on its length and the number of details. Each detail costs 1M.</p>
    <!-- Add a form to create a new ship -->
    <h2>Create a new ship</h2>
    <form id="newShipForm">
        <label for="shipName">Ship name:</label>
        <input type="text" id="shipName" name="shipName"><br><br>
        <label for="shipLength">Ship length:</label>
        <input type="number" id="shipLength" name="shipLength"><br><br>
        <label for="shipDetails">Number of details:</label>
        <input type="number" id="shipDetails" name="shipDetails"><br><br>
        <input type="submit" value="Create ship">
        <label for="shipStage">Ship stage:</label>
        <select id="shipStage" name="shipStage">
            <option value="1">Stage 1</option>
            <option value="2">Stage 2</option>
            <option value="3">Stage 3</option>
            <option value="4">Stage 4</option>
            <option value="5">Stage 5</option>
            <option value="6">Stage 6</option>
            <option value="7">Stage 7</option>
        </select><br><br>
    </form>
    <!-- Add a table to display the ships -->
    <h2>Ships</h2>
    <table id="shipsTable">
        <tr>
            <th>Name</th>
            <th>Length</th>
            <th>Details</th>
            <th>Popularity</th>
            <th>Profit</th>
            <th>Maintenance cost</th>
            <th>Look</th>
            <th></th>
        </tr>
    </table>
    <h2>Buy a ship</h2>
    <form id="buyShipForm">
        <label for="buyShipLength">Ship length:</label>
        <input type="number" id="buyShipLength" name="buyShipLength"><br><br>
        <label for="buyShipDetails">Number of details:</label>
        <input type="number" id="buyShipDetails" name="buyShipDetails"><br><br>
        <label for="buyShipStage">Ship stage:</label>
        <select id="buyShipStage" name="buyShipStage">
            <option value="1">Stage 1</option>
            <option value="2">Stage 2</option>
            <option value="3">Stage 3</option>
            <option value="4">Stage 4</option>
            <option value="5">Stage 5</option>
            <option value="6">Stage 6</option>
            <option value="7">Stage 7</option>
        </select><br><br>
        <input type="submit" value="Buy ship">
    </form>
<script>
// Add your JavaScript code here
let money = 10000000;
let ships = [];
let date = new Date(1880, 0);
let maxStageUnlocked = 1;
let shipsDatabase = [
    {
        name: "Titanic",
        length: 269,
        details: 11,
        stage: 3,
        year: 1912
    },
    ...
];
// Constants to control the game balance
const costPerMeter = 50000;
const costPerDetail = 1000000;
const basePopularity = 0;
const popularityPerMeter = 0.01;
const popularityPerDetail = 0.5;
const popularityLossPerMonth = 0.1;
const profitPerPopularityPoint = 100000;
const maintenanceCostPerMeter = 1000;
const maintenanceCostIncreasePerMonth = 100;
// Load the game state from local storage
function loadGameState() {
    let savedMoney = localStorage.getItem("money");
    if (savedMoney) {
      money = parseInt(savedMoney);
    }
    let savedShips = localStorage.getItem("ships");
    if (savedShips) {
      ships = JSON.parse(savedShips);
    }
    let savedDate = localStorage.getItem("date");
    if (savedDate) {
      date = new Date(savedDate);
    }
}
// Save the game state to local storage
function saveGameState() {
    localStorage.setItem("money", money);
    localStorage.setItem("ships", JSON.stringify(ships));
    localStorage.setItem("date", date.toISOString());
}
// Update the date display
function updateDateDisplay() {
    let monthNames = ["January", "February", "March", "April", "May", "June",
      "July", "August", "September", "October", "November", "December"
    ];
    let monthName = monthNames[date.getMonth()];
    let year = date.getFullYear();
    document.getElementById("date").innerHTML = monthName + " " + year;
}
// Update the money display
function updateMoneyDisplay() {
    document.getElementById("money").innerHTML = money;
}
// Calculate the cost of a ship
function calculateShipCost(length, details) {
    let cost = length * costPerMeter + details * costPerDetail;
    return cost;
}
// Calculate the popularity of a ship
function calculateShipPopularity(length, details, age) {
    let popularity = basePopularity + length * popularityPerMeter + details * popularityPerDetail - age * popularityLossPerMonth;
    return popularity;
}
// Calculate the profit of a ship
function calculateShipProfit(popularity) {
    let profit = popularity * profitPerPopularityPoint;
    return profit;
}
// Calculate the maintenance cost of a ship
function calculateMaintenanceCost(length, age) {
    let maintenanceCost = length * maintenanceCostPerMeter + age * maintenanceCostIncreasePerMonth;
    return maintenanceCost;
}
function addShip(name, length, details, stage) {
    if (stage > maxStageUnlocked) {
        alert("You haven't unlocked this stage yet.");
        return;
    }
    let stageCost = 0;
    if (stage == 2) {
        stageCost = 5000000;
    } else if (stage == 3) {
        stageCost = 10000000;
    } else if (stage == 4) {
        stageCost = 20000000;
    } else if (stage == 5) {
        stageCost = 40000000;
    } else if (stage == 6) {
        stageCost = 80000000;
    } else if (stage == 7) {
        stageCost = 160000000;
    }
    let cost = calculateShipCost(length, details) + stageCost;
    if (money >= cost) {
      money -= cost;
      let age = 0;
      let popularity = calculateShipPopularity(length, details, age);
      let profit = calculateShipProfit(popularity);
      let maintenanceCost = calculateMaintenanceCost(length, age);
      let yearCreated = date.getFullYear();
      ships.push({
        name: name,
        length: length,
        details: details,
        age: age,
        popularity: popularity,
        profit: profit,
        maintenanceCost: maintenanceCost,
        yearCreated: yearCreated,
        sold: false,
        stage: stage
      });
      updateShipsTable();
      updateMoneyDisplay();
      playSound("horn.mp3");
    } else {
      alert("You don't have enough money to build this ship.");
    }
}
// Scrap a ship
function scrapShip(index) {
    ships.splice(index, 1);
    updateShipsTable();
    playSound("destroy.mp3");
}
function updateShipsTable() {
    let table = document.getElementById("shipsTable");
    // Remove all rows except the header row
    for (let i = table.rows.length - 1; i > 0; i--) {
      table.deleteRow(i);
    }
    // Add a row for each ship
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      let row = table.insertRow(-1);
      row.insertCell(0).innerHTML = ship.name;
      row.insertCell(1).innerHTML = ship.length;
      row.insertCell(2).innerHTML = ship.details;
      row.insertCell(3).innerHTML = ship.popularity.toFixed(1);
      row.insertCell(4).innerHTML = ship.profit;
      row.insertCell(5).innerHTML = ship.maintenanceCost;
      
      // Add a cell to display the stage of the ship
      row.insertCell(6).innerHTML = "Stage " + ship.stage;
      
      let cell = row.insertCell(7);
      let button = document.createElement("button");
      button.innerHTML = "Scrap";
      button.onclick = function() {
        scrapShip(i);
      };
      cell.appendChild(button);
      cell = row.insertCell(8);
      button = document.createElement("button");
      button.innerHTML = "Sell";
      button.onclick = function() {
        sellShip(i);
      };
      cell.appendChild(button);
    }
}
// Handle the form submission
document.getElementById("newShipForm").onsubmit = function(event) {
    event.preventDefault();
    let name = document.getElementById("shipName").value;
    let length = document.getElementById("shipLength").value;
    let details = document.getElementById("shipDetails").value;
    addShip(name, length, details);
};
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
      ship.age += 1;
      ship.popularity = calculateShipPopularity(ship.length, ship.details, ship.age);
      ship.profit = calculateShipProfit(ship.popularity);
      ship.maintenanceCost = calculateMaintenanceCost(ship.length, ship.age);
      
      // TODO: Add code to handle random events such as a ship sinking
    }
    
    updateShipsTable();
    updateMoneyDisplay();
};
// Play a sound
function playSound(filename) {
    let audio = new Audio(filename);
    audio.play();
}
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    updateYearImage();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
    }
    updateMoneyDisplay();
    // Randomly sink a ship with a 5% probability
    if (Math.random() < 0.05 && ships.length > 0) {
        let index = Math.floor(Math.random() * ships.length);
        let ship = ships[index];
        alert("Oh no! The ship " + ship.name + " has sunk!");
        ships.splice(index, 1);
        updateShipsTable();
    }
};
// Load the game state and update the displays
loadGameState();
updateDateDisplay();
updateMoneyDisplay();
updateShipsTable();
// Update the year image
function updateYearImage() {
    let year = date.getFullYear();
    let imageSrc = "";
    if (year >= 2000) {
        imageSrc = "etap7.png";
    } else if (year >= 1970) {
        imageSrc = "etap6.png";
    } else if (year >= 1936) {
        imageSrc = "etap5.png";
    } else if (year >= 1923) {
        imageSrc = "etap4.png";
    } else if (year >= 1910) {
        imageSrc = "etap3.png";
    } else if (year >= 1896) {
        imageSrc = "etap2.png";
    } else if (year >= 1880) {
        imageSrc = "etap1.png";
    }
    document.getElementById("yearImage").src = imageSrc;
}
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    updateYearImage();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
      // TODO: Add code to handle random events such as a ship sinking
    }
    updateMoneyDisplay();
};
// Reset the game state
function resetGameState() {
    money = 10000000;
    ships = [];
    date = new Date(1880, 0);
    
    // Remove the saved game state from local storage
    localStorage.removeItem("money");
    localStorage.removeItem("ships");
    localStorage.removeItem("date");
    
    // Update the displays
    updateDateDisplay();
    updateMoneyDisplay();
    updateShipsTable();
}
// Save the game state every 30 seconds
setInterval(saveGameState, 30000);
// Handle the reset button click
document.getElementById("resetButton").onclick = function() {
  if (confirm("Are you sure you want to reset the game? This will delete your saved game.")) {
     resetGameState();
  }
};
// Play background music
playSound("song.mp3");
function unlockNextStage() {
    if (maxStageUnlocked >= 7) {
        alert("You have already unlocked all stages.");
        return;
    }
    let cost = (maxStageUnlocked + 1) * 10000000;
    if (money >= cost) {
        money -= cost;
        maxStageUnlocked += 1;
        updateMoneyDisplay();
        alert("You unlocked stage " + maxStageUnlocked + ".");
    } else {
        alert("You don't have enough money to unlock the next stage.");
    }
}
function sellShip(index) {
    let ship = ships[index];
    if (ship.sold) {
        alert("This ship has already been sold.");
        return;
    }
    let cost = calculateShipCost(ship.length, ship.details);
    let sellPrice = cost / 2;
    if (Math.random() < 0.5) {
        money += sellPrice;
        updateMoneyDisplay();
        ship.sold = true;
        updateShipsTable();
        alert("You sold the ship for " + sellPrice + ".");
    } else {
        alert("No one wants to buy this ship.");
    }
}
function buyShip(length, details, stage) {
    let ship = shipsDatabase.find(function(ship) {
        return ship.length == length && ship.details == details && ship.stage == stage && ship.year <= date.getFullYear();
    });
    if (ship) {
        let cost = calculateShipCost(length, details) / 2;
        if (Math.random() < 0.5) {
            if (money >= cost) {
                money -= cost;
                ships.push({
                    name: ship.name,
                    length: length,
                    details: details,
                    age: 0,
                    popularity: calculateShipPopularity(length, details, 0),
                    profit: calculateShipProfit(calculateShipPopularity(length, details, 0)),
                    maintenanceCost: calculateMaintenanceCost(length, 0),
                    yearCreated: date.getFullYear(),
                    sold: false,
                    stage: stage
                });
                updateShipsTable();
                updateMoneyDisplay();
                alert("You bought the " + ship.name + " for " + cost + ".");
            } else {
                alert("You don't have enough money to buy this ship.");
            }
        } else {
            alert("The seller doesn't want to sell you this ship.");
        }
    } else {
        alert("There is no ship with these characteristics for sale.");
    }
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
    <title>Transatlantic Simulator</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Parisienne&display=swap');
        body {
            font-family: 'Parisienne', cursive;
            background-color: darkblue;
            color: gold;
        }
        table {
            border-collapse: collapse;
            width: 100%;
        }
        table, th, td {
            border: 1px solid lightblue;
            padding: 8px;
        }
        th {
            text-align: left;
            background-color: #f2f2f2;
        }
        tr:hover {
            background-color: #f5f5f5;
        }
    </style>
</head>
<body>
    <h1>Transatlantic Simulator</h1>
    <p>Date: <span id="date">January 1880</span></p>
    <p>Money: <span id="money">10M</span></p>
    <button id="nextMonthButton">Next month</button>
    <button id="resetButton">Reset game</button>
    <img id="yearImage" src="">
    <p>Start with 10M of money. You can build transatlantic ships and choose the length and details.</p>
    <p>Base cost: The cost of a ship depends on its length and the number of details. Each detail costs 1M.</p>
    <!-- Add a form to create a new ship -->
    <h2>Create a new ship</h2>
    <form id="newShipForm">
        <label for="shipName">Ship name:</label>
        <input type="text" id="shipName" name="shipName"><br><br>
        <label for="shipLength">Ship length:</label>
        <input type="number" id="shipLength" name="shipLength"><br><br>
        <label for="shipDetails">Number of details:</label>
        <input type="number" id="shipDetails" name="shipDetails"><br><br>
        <input type="submit" value="Create ship">
    </form>
    <!-- Add a table to display the ships -->
    <h2>Ships</h2>
    <table id="shipsTable">
        <tr>
            <th>Name</th>
            <th>Length</th>
            <th>Details</th>
            <th>Popularity</th>
            <th>Profit</th>
            <th>Maintenance cost</th>
            <th>Look</th>
            <th></th>
        </tr>
    </table>
<script>
// Add your JavaScript code here
let money = 10000000;
let ships = [];
let date = new Date(1880, 0);
// Constants to control the game balance
const costPerMeter = 50000;
const costPerDetail = 1000000;
const basePopularity = 0;
const popularityPerMeter = 0.01;
const popularityPerDetail = 0.5;
const popularityLossPerMonth = 0.1;
const profitPerPopularityPoint = 100000;
const maintenanceCostPerMeter = 1000;
const maintenanceCostIncreasePerMonth = 100;
// Load the game state from local storage
function loadGameState() {
    let savedMoney = localStorage.getItem("money");
    if (savedMoney) {
      money = parseInt(savedMoney);
    }
    let savedShips = localStorage.getItem("ships");
    if (savedShips) {
      ships = JSON.parse(savedShips);
    }
    let savedDate = localStorage.getItem("date");
    if (savedDate) {
      date = new Date(savedDate);
    }
}
// Save the game state to local storage
function saveGameState() {
    localStorage.setItem("money", money);
    localStorage.setItem("ships", JSON.stringify(ships));
    localStorage.setItem("date", date.toISOString());
}
// Update the date display
function updateDateDisplay() {
    let monthNames = ["January", "February", "March", "April", "May", "June",
      "July", "August", "September", "October", "November", "December"
    ];
    let monthName = monthNames[date.getMonth()];
    let year = date.getFullYear();
    document.getElementById("date").innerHTML = monthName + " " + year;
}
// Update the money display
function updateMoneyDisplay() {
    document.getElementById("money").innerHTML = money;
}
// Calculate the cost of a ship
function calculateShipCost(length, details) {
    let cost = length * costPerMeter + details * costPerDetail;
    return cost;
}
// Calculate the popularity of a ship
function calculateShipPopularity(length, details, age) {
    let popularity = basePopularity + length * popularityPerMeter + details * popularityPerDetail - age * popularityLossPerMonth;
    return popularity;
}
// Calculate the profit of a ship
function calculateShipProfit(popularity) {
    let profit = popularity * profitPerPopularityPoint;
    return profit;
}
// Calculate the maintenance cost of a ship
function calculateMaintenanceCost(length, age) {
    let maintenanceCost = length * maintenanceCostPerMeter + age * maintenanceCostIncreasePerMonth;
    return maintenanceCost;
}
// Add a new ship
function addShip(name, length, details) {
    let cost = calculateShipCost(length, details);
    if (money >= cost) {
      money -= cost;
      let age = 0;
      let popularity = calculateShipPopularity(length, details, age);
      let profit = calculateShipProfit(popularity);
      let maintenanceCost = calculateMaintenanceCost(length, age);
      let yearCreated = date.getFullYear();
      ships.push({
        name: name,
        length: length,
        details: details,
        age: age,
        popularity: popularity,
        profit: profit,
        maintenanceCost: maintenanceCost,
        yearCreated: yearCreated
      });
      updateShipsTable();
      updateMoneyDisplay();
      playSound("horn.mp3");
    } else {
      alert("You don't have enough money to build this ship.");
    }
}
// Scrap a ship
function scrapShip(index) {
    ships.splice(index, 1);
    updateShipsTable();
    playSound("destroy.mp3");
}
// Update the ships table
function updateShipsTable() {
    let table = document.getElementById("shipsTable");
    // Remove all rows except the header row
    for (let i = table.rows.length - 1; i > 0; i--) {
      table.deleteRow(i);
    }
    // Add a row for each ship
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      let row = table.insertRow(-1);
      row.insertCell(0).innerHTML = ship.name;
      row.insertCell(1).innerHTML = ship.length;
      row.insertCell(2).innerHTML = ship.details;
      row.insertCell(3).innerHTML = ship.popularity.toFixed(1);
      row.insertCell(4).innerHTML = ship.profit;
      row.insertCell(5).innerHTML = ship.maintenanceCost;
      
      // Add a cell to display the look of the ship
      let look = "";
      if (ship.yearCreated >= 2000) {
          look = "etap7";
      } else if (ship.yearCreated >= 1970) {
          look = "etap6";
      } else if (ship.yearCreated >= 1936) {
          look = "etap5";
      } else if (ship.yearCreated >= 1923) {
          look = "etap4";
      } else if (ship.yearCreated >= 1910) {
          look = "etap3";
      } else if (ship.yearCreated >= 1896) {
          look = "etap2";
      } else if (ship.yearCreated >= 1880) {
          look = "etap1";
      }
      row.insertCell(6).innerHTML = look;
      
      let cell = row.insertCell(7);
      let button = document.createElement("button");
      button.innerHTML = "Scrap";
      button.onclick = function() {
        scrapShip(i);
      };
      cell.appendChild(button);
    }
}
// Handle the form submission
document.getElementById("newShipForm").onsubmit = function(event) {
    event.preventDefault();
    let name = document.getElementById("shipName").value;
    let length = document.getElementById("shipLength").value;
    let details = document.getElementById("shipDetails").value;
    addShip(name, length, details);
};
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
      ship.age += 1;
      ship.popularity = calculateShipPopularity(ship.length, ship.details, ship.age);
      ship.profit = calculateShipProfit(ship.popularity);
      ship.maintenanceCost = calculateMaintenanceCost(ship.length, ship.age);
      
      // TODO: Add code to handle random events such as a ship sinking
    }
    
    updateShipsTable();
    updateMoneyDisplay();
};
// Play a sound
function playSound(filename) {
    let audio = new Audio(filename);
    audio.play();
}
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    updateYearImage();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
    }
    updateMoneyDisplay();
    // Randomly sink a ship with a 5% probability
    if (Math.random() < 0.05 && ships.length > 0) {
        let index = Math.floor(Math.random() * ships.length);
        let ship = ships[index];
        alert("Oh no! The ship " + ship.name + " has sunk!");
        ships.splice(index, 1);
        updateShipsTable();
    }
};
// Load the game state and update the displays
loadGameState();
updateDateDisplay();
updateMoneyDisplay();
updateShipsTable();
// Update the year image
function updateYearImage() {
    let year = date.getFullYear();
    let imageSrc = "";
    if (year >= 2000) {
        imageSrc = "etap7.png";
    } else if (year >= 1970) {
        imageSrc = "etap6.png";
    } else if (year >= 1936) {
        imageSrc = "etap5.png";
    } else if (year >= 1923) {
        imageSrc = "etap4.png";
    } else if (year >= 1910) {
        imageSrc = "etap3.png";
    } else if (year >= 1896) {
        imageSrc = "etap2.png";
    } else if (year >= 1880) {
        imageSrc = "etap1.png";
    }
    document.getElementById("yearImage").src = imageSrc;
}
// Handle the next month button click
document.getElementById("nextMonthButton").onclick = function() {
    // Advance to the next month
    date.setMonth(date.getMonth() + 1);
    updateDateDisplay();
    updateYearImage();
    // Update the game state for the next month
    for (let i = 0; i < ships.length; i++) {
      let ship = ships[i];
      money += ship.profit - ship.maintenanceCost;
      // TODO: Add code to handle random events such as a ship sinking
    }
    updateMoneyDisplay();
};
// Reset the game state
function resetGameState() {
    money = 10000000;
    ships = [];
    date = new Date(1880, 0);
    
    // Remove the saved game state from local storage
    localStorage.removeItem("money");
    localStorage.removeItem("ships");
    localStorage.removeItem("date");
    
    // Update the displays
    updateDateDisplay();
    updateMoneyDisplay();
    updateShipsTable();
}
// Save the game state every 30 seconds
setInterval(saveGameState, 30000);
// Handle the reset button click
document.getElementById("resetButton").onclick = function() {
  if (confirm("Are you sure you want to reset the game? This will delete your saved game.")) {
     resetGameState();
  }
};
// Play background music
playSound("song.mp3");
</script>
</body>
</html>