%%html
<head>
    <script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>var define = null;</script>
    <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
    <style>
        @import url('https://fonts.googleapis.com/css?family=Press+Start+2P');
        .fisherman {
            position: absolute;
            left: 335px;
            top: 235px;
        }
        .hut {
            position: absolute;
            top: 205px;
            left: 8px;
        }
        .water {
            position: absolute;
            top: 279px;
            height: 58px;
        }
        .container {
            position: absolute;
        }
        .background {
            object-fit: cover;
        }
        .boat {
            position: absolute;
            top: 265px;
            left: 300px;
        }
        .moneyIcon {
            width: 40px;
            position: absolute;
            top: 10px;
            left: 420px;
        }
        .money {
            font-family: "Oxygen", sans-serif;
            font-size: 26px;
            position: absolute;
            top: -10px;
            left: 460px;
            color: white;
        }
        .catchIcon {
            position: absolute;
            top: 170px;
            left: 320px;
        }
        .catchText {
            position: absolute;
            top: 190px;
            left: 255px;
            text-align: center;
            font-family: "Oxygen", sans-serif;
            color: white;
        }
        .catchEarnings {
            position: absolute;
            top: 205px;
            left: 317px;
            text-align: center;
            font-family: "Oxygen", sans-serif;
            color: white;
        }
        .upgradeButton {
            position: absolute;
            left: 30px;
            background-color: transparent;
            border: none;
            outline: none;
        }
        .upgradeDesc {
            position: absolute;
            left: 30px;
            font-family: "Oxygen", sans-serif;
            color: white;
        }



    </style>
</head>
    <img class="background" src="images/fishing/background.png"></img>
    <img class="hut" src="images/fishing/hut.png"></img>
    <div class="water-container">
        <img class="water" id="water1" src="images/fishing/water.png" style="left: 8px"></img>
        <img class="water" id="water2" src="images/fishing/water.png" style="left: 200px"></img>
        <img class="water" id="water3" src="images/fishing/water.png" style="left: 392px"></img>
    </div>
       

    <img class="fisherman" id="fisherman" src="images/fishing/hook1.png"></img>
    <img class="boat" id="boat" src="images/fishing/boat.png"></img>

    <img class="moneyIcon" id="moneyIcon" src="images/fishing/money.png"></img>
    <p class="money" id="money" data-money = "0">$0</p>

<img class="catchIcon" id="catchIcon" src="images/fishing/fish1.png" style="display: none"></img>
<p class="catchText" id="catchText" style="display: none"></p>
<p class="catchEarnings" id="catchEarnings" style="display: none"></p>

<button id="fishingSpeedUpgrade" class="upgradeButton" style="top: 30px"><img src="images/fishing/upgrade1.png"></img></button>
<p class="upgradeDesc" style="top: 55px">Catch Rate</p>
<p id="fishingSpeedUpgradeCost" class="upgradeDesc" style="top: 70px">$20</p>

<button id="fishingQualityUpgrade" class="upgradeButton" style="top: 90px"><img src="images/fishing/upgrade3.png"></img></button>
<p class="upgradeDesc" style="top: 115px">Catch Quality</p>
<p id="fishingQualityUpgradeCost" class="upgradeDesc" style="top: 130px">$20</p>

<button id="fishingEarningsUpgrade" class="upgradeButton" style="top: 150px"><img src="images/fishing/upgrade2.png"></img></button>
<p class="upgradeDesc" style="top: 175px">Sell Rate</p>
<p id="fishingEarningsUpgradeCost" class="upgradeDesc" style="top: 190px">$20</p>


<script>
    $(document).ready(function() {
        //Define constants from HTML
        const fisherman = document.getElementById("fisherman");
        const water1 = document.getElementById("water1");
        const water2 = document.getElementById("water2");
        const water3 = document.getElementById("water3");
        const boat = document.getElementById("boat");
        const money = document.getElementById("money");
        const catchIcon = document.getElementById("catchIcon");
        const catchText = document.getElementById("catchText");
        const catchEarnings = document.getElementById("catchEarnings");
        const fishingSpeedUpgrade = document.getElementById("fishingSpeedUpgrade");
        const fishingSpeedUpgradeCost = document.getElementById("fishingSpeedUpgradeCost");
        const fishingCatchMultiplierUpgrade = document.getElementById("fishingQualityUpgrade");
        const fishingCatchMultiplierUpgradeCost = document.getElementById("fishingQualityUpgradeCost");
        const fishingLuckUpgrade = document.getElementById("fishingEarningsUpgrade");
        const fishingLuckUpgradeCost = document.getElementById("fishingEarningsUpgradeCost");
        
        //For animation
        let status = 0;
        let frame = 1;
        let wavesFrame = 1;
        
        //For initial stats
        let catchRate = 0.05;
        let luck = 0; //Int 0-10
        let catchMultiplier = 1;

        //Customizable messages and base rewards
        const catchMessages = ["You caught a epic treasure!", "    You caught an exotic tropical fish!", "      You caught a rare salmon!", "     You caught a common trout!"]
        const baseCatchRewards = [100, 60, 40, 20];

        //For upgrades, customizable
        const fishingSpeedCosts = [20, 50, 100, 200, 500];
        const fishingSpeedUpgrades = [0.05, 0.08, 0.1, 0.15, 0.2];
        let currentFishingSpeedUpgrade = 0;

        const luckCosts = [20, 50, 100, 200, 500];
        const luckUpgrades = [0, 2, 4, 7, 10];
        let currentLuckUpgrade = 0;


        const catchMultiplierCosts = [20, 50, 100, 200, 500];
        const catchMultiplierUpgrades = [1.2, 1.3, 1.5, 1.7, 2];
        let currentCatchMultiplierUpgrade = 0;

        //Utility functions
        function setFishermanStatus(newStatus) {
            frame = 1;
            if(newStatus == "idle") {
                status = 0;
            } else if(newStatus == "hook") {
                status = 1;
            } else {
                console.log("Error, status set to invalid value");
            }
        }

        function updateMoney(moneyUpdate) {
            moneyAmount = parseInt(money.getAttribute('data-money'))  + moneyUpdate;
            money.setAttribute('data-money', moneyAmount);
            money.textContent = "$" + moneyAmount;
        }

        function getMoney() {
            return parseInt(money.getAttribute('data-money'));
        }

        function setMessageVisibility(visibility) {
            let newDisplay = "";
            if(visibility) {
                newDisplay = "block";
            } else {
                newDisplay = "none";
            }

            catchIcon.style.display = newDisplay;
            catchText.style.display = newDisplay;
            catchEarnings.style.display = newDisplay;
        }
      
        //Set up animation timer
        function animate() {
            // Was going to do switch statements but energetic programming bad
            if(status == 0) { //Idle 
                if(frame == 1) {
                    fisherman.src = "images/fishing/idle2.png";
                    frame = 2;
                } else {
                    fisherman.src = "images/fishing/idle1.png";
                    frame = 1;
                }
                checkForCatch();
            } else if(status == 1) { //Caught fish
                let source = "images/fishing/";
                if(frame < 5) {
                    source += "hook" + (frame+1) + ".png"
                    frame +=1;
                } else {
                    setFishermanStatus("idle")
                    source += "idle1.png"
                }
                fisherman.src = source;
            }
        }

        function waves() {
            waterLevelChange = parseInt(6*Math.sin(wavesFrame/100));

            water1.style.top = (279 + waterLevelChange) + "px";
            water2.style.top = (279 + waterLevelChange) + "px";
            water3.style.top = (279 + waterLevelChange) + "px";

            boat.style.top = (272 + waterLevelChange*1.3) + "px"; //Boat+Fisherman go 'ride' the waves
            fisherman.style.top = (237 + waterLevelChange*1.3) + "px";
            wavesFrame += 1;
        }

        function checkForCatch() {
            if(Math.random() > catchRate) {
                return; //Returns if not a catch
            }
            
            setFishermanStatus("hook");

            //Choose what fish to catch
            let randomNumber = parseInt(Math.random() * 100);
            let catchThresholds =  [95-2*luck, 80-4*luck, 60-6*luck, 0];

            i=0;
            catchSelected = false; //To prevent duplicate catches
            catchThresholds.forEach((threshold) => {
                if(!catchSelected && randomNumber >= threshold) {
                    updateMoney(parseInt(baseCatchRewards[i]*catchMultiplier));

                    //Show message
                    catchIcon.src = "images/fishing/fish" + (i) + ".png";
                    catchText.textContent = catchMessages[i];
                    catchEarnings.textContent = "+$" + parseInt(baseCatchRewards[i]*catchMultiplier);
                    setMessageVisibility(true);

                    setTimeout(()=> {
                        setMessageVisibility(false); //Hide message 1200 milliseconds later
                    },1200);
                    catchSelected = true;
                }
                i += 1;
            });
        }

        //Upgrades

        //Fishing speed
        fishingSpeedUpgrade.addEventListener("click", function(){
            let cost = fishingSpeedCosts[currentFishingSpeedUpgrade];
            let currentMoney = getMoney();

            //Check if it is ok to upgrade, then change text and variables
            if(currentMoney >= cost && currentFishingSpeedUpgrade < fishingSpeedCosts.length) { 
                updateMoney(-cost);
                currentFishingSpeedUpgrade += 1;
                catchRate = fishingSpeedUpgrades[currentFishingSpeedUpgrade];
                
                //Check if you have maxed out level now
                if(currentFishingSpeedUpgrade >= fishingSpeedCosts.length) {
                    fishingSpeedUpgradeCost.textContent = "Maxed"
                } else {
                    fishingSpeedUpgradeCost.textContent = "$" +  fishingSpeedCosts[currentFishingSpeedUpgrade];
                }
            }
        });

        //Luck Upgrade
        fishingLuckUpgrade.addEventListener("click", function(){
            let cost = luckCosts[currentLuckUpgrade];
            let currentMoney = getMoney();

            if(currentMoney >= cost && currentLuckUpgrade < luckCosts.length) { 
                updateMoney(-cost);
                currentLuckUpgrade += 1;
                luck = currentLuckUpgrade * 2;

                if(currentLuckUpgrade >= luckCosts.length) {
                    fishingLuckUpgradeCost.textContent = "Maxed";
                } else {
                    fishingLuckUpgradeCost.textContent = "$" + luckCosts[currentLuckUpgrade];
                }
            }
        });

        //Catch multiplier
        fishingCatchMultiplierUpgrade.addEventListener("click", function(){
            let cost = catchMultiplierCosts[currentCatchMultiplierUpgrade];
            let currentMoney = getMoney();

            if(currentMoney >= cost && currentCatchMultiplierUpgrade < catchMultiplierCosts.length) { 
                updateMoney(-cost);
                currentCatchMultiplierUpgrade += 1;
                catchMultiplier = catchMultiplierUpgrades[currentCatchMultiplierUpgrade];

                if(currentCatchMultiplierUpgrade >= catchMultiplierCosts.length) {
                    fishingCatchMultiplierUpgradeCost.textContent = "Maxed";
                } else {
                    fishingCatchMultiplierUpgradeCost.textContent = "$" + catchMultiplierCosts[currentCatchMultiplierUpgrade];
                }
            }
        });

        //Start animations
        setInterval(animate, 200);
        setInterval(waves, 20);
    });
</script>
</img> </img>
</img> </img> </img>
</img> </img> </img>

$0

</img>

Catch Rate

$20

Catch Quality

$20

Sell Rate

$20

%%html
<body>
    <h3>Username</h3>
    <textarea id="username"></textarea>
    <h3>Score</h3>
    <textarea id="score"></textarea><br>
    <button id="send">Send Score</button>
</body>

<script>
    const username = document.getElementById("username");
    const score = document.getElementById("score");
    const send = document.getElementById("send");

    send.addEventListener("click", function(){
        var url = "https://taylorswifties.duckdns.org/api/nfts/create";
        fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({"username": username.val(), "score": score.val()})
        })
        .then((response) => response.json())
        .then(prep(id))
    });
</script>

Username

Score


%%html
<head>
    <!-- load jQuery and DataTables syle and scripts -->
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
    <script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>var define = null;</script>
    <script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
</head>
<table id="flaskTable" class="table" style="width:100%">
    <thead id="flaskHead">
        <tr>
            <th>ID</th>
            <th>Score</th>
            <th>Username</th>
        </tr>
    </thead>
    <tbody id="flaskBody"></tbody>
</table>

<script>
  $(document).ready(function() {
    fetch('https://taylorswifties.duckdns.org//api/scores/', { mode: 'cors' })
    .then(response => {
      if (!response.ok) {
        throw new Error('API response failed');
      }
      return response.json();
    })
    .then(data => {
      for (const row of data) {
        // BUG warning/resolution - DataTable requires row to be single append
        $('#flaskBody').append('<tr><td>' + 
            row.id + '</td><td>' + 
            row.score + '</td><td>' + 
            row.username + '</td><td>');
      }
      // BUG warning - Jupyter does not show Datatable controls, works on deployed GitHub pages
      $("#flaskTable").DataTable();
    })
    .catch(error => {
      console.error('Error:', error);
    });
  });
</script>
ID Score Username