Code viewer for World: CA318 Practical
//CA318 Assignment
//Samuel Barnett
//21342951

//Below are worlds I used for help...

// [1] "Chat with GPT model" at https://ancientbrain.com/edit.world.php?world=5340243601
// [2] "Finnegans Wake" at https://ancientbrain.com/world.php?world=6149262508


//My OpenAI Key is below:

//"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"

//Use this key to sucessfully generate responses from the prompt


let API_KEY = ""; //Want to change this value when we set it in function. Set it as empty for now...
const API_URL = "https://api.openai.com/v1/chat/completions"; //OpenAI url


//Web pages HTML and styling....
$('body').css( "margin", "25px" );
$('body').css( "padding", "25px" );
  
document.write ( ` 

<head>
  <script async src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>

<style>
  body {
    background-image: url('/uploads/barnets2/1701547422.png');
    background-size: cover;
    color: black;
    font-family: 'Times New Roman', serif;
    margin: 0;
  }

  .header-container {
    display: flex;
    align-items: center;
    background-color: CadetBlue;
    border: 1px solid black;
    padding: 20px;
    border-radius: 10px;
    text-align: center;
  }
  
  #resultContainer {
    background-color: Cornsilk;
    border: 1px solid black;
    border-radius: 10px;
    padding: 20px;
    margin-top: 20px; 
    height: 100vh; 
  }

  #resultText {
    font-family: 'Times New Roman', serif;
    font-size: 16px;
  } 
  
  #apiKeyContainer {
    text-align: center;
    margin-bottom: 20px;
  }

  #apiKeyInput {
    padding: 5px;
  }

  #setApiKeyBtn {
    padding: 5px 10px;
  }

</style>

<div class="header-container">
    <div style="flex: 1;">
        <img src="/uploads/barnets2/chat_image.png" alt="Left Image" style="width: 80%; border-top-left-radius: 7px; border-bottom-left-radius: 7px;">
    </div>
    

    <div style="flex: 3; padding: 0 20px;">
        <h1 style="font-family: 'Aptos Black', sans-serif; font-size: 42px;">CA318 Practical</h1>
        <p style="font-size: 24px;">
            Sam Barnett: 21342951
            <br>
            Assignment Specification:
            <a href='https://humphryscomputing.com/ca318/practical.html'>CA318 AI Practical</a>.
            <br>
            I'm using the
            <a href="https://en.wikipedia.org/wiki/OpenAI">OpenAI</a> API for this project.
            <br>
            Enter a prompt to GPT 3.5, and it will provide a response to you. You can adjust the "temperature" of the response by
            moving the slider. Lower temps mean fewer risks (more accurate and simple), with higher temps leading to more
            creative and risky completions. Experiment with moving the slider to see the differences in the response!
            <br>
            The response from GPT may take some time to load depending on the prompt you have entered.
        </p>
        
    
        <div style="width:60vw; background-color: Lavender; border: 1px solid black; margin: 20px; padding: 20px;">
            <div id="apiKeyContainer">
                <input id="apiKeyInput" type="text" placeholder="Enter OpenAI key">
                <button id="setApiKeyBtn" class="ab-normbutton" onclick="setApiKey()">Set API Key</button>
            </div>

            <h2 style="font-family: 'Segoe Print', sans-serif; font-size: 20px;">Enter a Prompt to GPT</h2>
            <input style="width:50vw;" id="promptInput" type="text" placeholder="Enter Prompt..." disabled>
            <input type="range" id="temperatureSlider" min="0" max="1" step="0.1" value="0.7" onchange="updateTemperature(this.value)">
            <button id="generateBtn" class="ab-normbutton">Generate</button>
        </div>
        
        <div>
            <label for="temperatureSlider">Temperature:</label>
            <span id="currentTemperature">0.7</span>
        </div>

        <p>GPT response will appear below</p>
    </div>

    <div style="flex: 1;">
        <img src="/uploads/barnets2/chat_image.png" alt="Right Image" style="width: 80%; border-top-right-radius: 7px; border-bottom-right-radius: 7px;">
    </div>
</div>

<pre></pre>

<div id="resultContainer" class="mt-4 h-48 overflow-y-auto">
    <p id="resultText" class="whitespace-pre-line"></p>
</div>

` );

var thedata = { //I've taken this var from "Chat with GPT model"
     "model": "gpt-3.5-turbo",
     "temperature": 0.7,
     "messages": [{
         "role": "user", 
         "content": resultText
        }] 
   };

function setApiKey() { //Function to set the API key inputted by user to the variable API_KEY
    const apiKeyInput = document.getElementById("apiKeyInput");
    API_KEY = apiKeyInput.value;
    console.log("API Key Set")
    
    // I wanted to ensure users set their API key before using prompt
    // Below will enable the prompt once key is set
    const promptInput = document.getElementById("promptInput");
    promptInput.removeAttribute("disabled");
}


function updateTemperature(value) {
    $("#currentTemperature").html(value); // Update the displayed temperature
    thedata.temperature = parseFloat(value);
}

document.addEventListener("DOMContentLoaded", function () { //This is to make sure doc is fully loaded first.
    const generateBtn = document.getElementById("generateBtn");
    const promptInput = document.getElementById("promptInput");
    const resultText = document.getElementById("resultText"); //Three values defined in my HTML.

    const generate = async () => {
        try {
            const response = await fetch(API_URL, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": "Bearer " + API_KEY
                },
                body: JSON.stringify({
                    model: "gpt-3.5-turbo",
                    messages: [{ role: "user", content: promptInput.value }],
                }),
            });

            const data = await response.json();

            // I want to make sure data.choices[0] exists and has the message property.
            // I introduced this as I was getting console errors when I used a bad API key
    
            if (data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content) {
                resultText.innerText = data.choices[0].message.content;
            } else { // data.choices would be empty/undefined in this case...
                console.error("There is an issue with your API key. Ensure you are setting a valid key. My API Key is located at the top of the code.");
                resultText.innerText = "API could not provide a response. Ensure you are using a valid OpenAI Key";
            }

        } catch (error) {
            console.error("Error: ", error);
        }
    };

    generateBtn.addEventListener("click", generate);
    promptInput.addEventListener("keyup", (event) => {
        if (event.key === "Enter") {
            generate(); //if user presses enter, generate response to their text...
        }
    });
});