<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Want You Gone</title>
		<meta
			name="description"
			content="poketube credits"
		/>
		<meta property="og:title" content="file://GLaDOS/poketube/want_you_gone.sh" />
		<meta property="og:type" content="article" />
    <meta name="theme-color" content="#FFA500">
		<meta
			property="og:description"
			content="poketube credits"
		/>
		<meta name="twitter:card" content="summary" />
    <link rel="icon" type="image/x-icon" href="/css/yt-ukraine.svg">
    
    <style>
    body::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: repeating-linear-gradient(0deg, #00000050 3px, transparent 5px);
  pointer-events: none;
}
::selection {
  background: #0080FF;
  text-shadow: none;
}
pre {
  margin: 25px;
}
body {
  background-color: black;
  /* 92, 56, 17*/
  background-image: radial-gradient(rgba(205, 147, 21, 0.75), black 120%);
  height: 100vh;
  margin: 0;
  overflow: hidden;
  padding: 2rem;
  color: white;
  font: 1.3rem Inconsolata, monospace;
  text-shadow: 0 0 5px #C8C8C8;
}

#credits {
  position: fixed;
  bottom: 0;
  right: 0;
  z-index: -1;
  padding: 2rem;
  text-align: end;
  color: orange;
}

.apperture {
  position: fixed;
  top: 0;
  right: 0;
  z-index: -1;
  padding: 2rem;
}

audio {
	position: fixed;
	bottom: 1em;
	right: 1em;
  width: 25%;
}
    </style>
	</head>
	<body>
		<div id="content">
			
		</div>
    <div id="credits">
      
    </div>
    <audio id="song" controls>
       <source src="https://cdn.glitch.me/cd1dbcf6-511c-48cb-afaa-262e74faa90a%2FPortal%202%20-%20End%20Credits%20Song%20'Want%20You%20Gone'%20by%20Jonathan%20Coulton%20%5B1080p%20HD%5D-dVVZaZ8yO6o.mp3?v=1638607967369" type="audio/mpeg">
     </audio>
    <image href="https://p.poketube.fun/https://cdn.glitch.global/cd1dbcf6-511c-48cb-afaa-262e74faa90a%2Fapperture.png?v=1638618539245" class="apperture"></image>
		<noscript>
			FATAL ERROR: Cannot load file, please enable JavaScript
		</noscript>
      <script type="text/javascript">
<!--//--><![CDATA[//><!--
/**
 * @licstart The following is the entire license notice for the JavaScript
 * code in this page.
 *
 *  Copyright (C) 2021-2022 POKETUBE (https://codeberg.org/Ashley/poketube)
 *
 * The JavaScript code in this page is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License
 * (GNU GPL) as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.  The code is
 * distributed WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU GPL
 * for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you may
 * distribute non-source (e.g., minimized or compacted) forms of that code
 * without the copy of the GNU GPL normally required by section 4, provided
 * you include this license notice and a URL through which recipients can
 * access the Corresponding Source.
 *
 * @licend The above is the entire license notice for the JavaScript code
 * in this page.
 */

//--><!]]>
</script>
    
		<script>let audio = document.getElementById("song");
const contentEl = document.getElementById("content");
const creditsEl = document.getElementById("credits");

const getTime = () => audio.currentTime * 1000; // ms
const waitForInteraction = () => new Promise(res => document.body.addEventListener("click", res));

const main = async () => {
  await SCHEMAS.blink();
  
  await loadTimings();
  
  await SCHEMAS.write(["", "[info] Click to play"]);
  await waitForInteraction();
  await SCHEMAS.write(timedText("\n[info] Playing...", 200));
  await SCHEMAS.clear();
  
  audio.play();
  
}

const TimingActions = {
  append: (x) => {
    appendContent(x.text)
    //console.log(x)
  },
  clear: () => {
    setContent("")
    //console.log("clear")
  },
}

const CreditsActions = {
  append: (x) => appendCredits(x.text),
}

let creditsContent = ""
let appendCredits = str => {
  setCredits(creditsContent + str)
}
let setCredits = str => {
  creditsContent = str
}

let timingLastTime = 0;
let creditsIndex = 0;
let updateDisplay = () => {
  let time = audio.currentTime * 1000;
  let Tactions = [];
  let Cactions = []
  timings.filter(x => timingLastTime <= x.time && x.time < time).forEach(x => Tactions.push(x));
  creditsTimings.filter(x => timingLastTime <= x.time && x.time < time).forEach(x => Cactions.push(x));
  timingLastTime = time
  
  //console.log(time, Tactions)
  
  Tactions.forEach(x => {
    TimingActions[x.type](x);
  })
  Cactions.forEach(x => CreditsActions[x.type](x))
}

setInterval(() => {
  if(!audio.paused) updateDisplay()
}, 1000/30)



let timings = [];
let creditsTimings = [];

const loadTimings = async () => {
  creditsTimings = await loadCreditsTimings();
  timings = loadSongTimings();
}

const Start = () => {
  let time = 0;
  
  
}

const StartCredits = () => {
  let time = 0;
  let intervalSpeed = 30;
  
  let lastIndex = -1;
  
  let setContent = str => {
    content = str;
  };

  let appendContent = str => {
    setContent(content + str);
  };
  
  setInterval(() => {
    time = getTime();
    
    
  }, intervalSpeed);
}




let blink = false;
let blinkDelay = 500;
let cursorShown = false;

let content = "";

let setContent = str => {
  content = str;
};

let appendContent = str => {
  setContent(content + str);
};

let wait = ms => new Promise(r => setTimeout(() => r(), ms));

window.int1 = setInterval(() => contentEl.innerText = content + (blink && cursorShown ? "_" : ""), 1000/30);
window.int2 = setInterval(() => cursorShown = !cursorShown, blinkDelay);

let ccursorShown = true
window.int3 = setInterval(() => creditsEl.innerText = creditsContent + (ccursorShown ? "_" : ""), 1000/30);
window.int4 = setInterval(() => ccursorShown = !ccursorShown, blinkDelay);


const loadCreditsTimings = async () => {
  let res = await fetch("https://ashley0143.xyz/credits.txt");
  let credits = (await res.text()).split("\n");
  
  let _timings = [];
  let _time = 0;
  
  const creditsDur = (audio.duration * 1000) - 20000;
  const delay = creditsDur / credits.join("").length;
  
  let append = str => {
    _timings.push({
      type: "append",
      time: _time,
      text: str,
    });
  };
  
  for(let i = 0 ; credits.length != i ; i++){
    let line = credits[i];
    let t = 0;
    while (line.length > t) {
      let char = line[t];
      let charLast = line[t - 1];
      append(charLast == " " ? " " + char : char);
      t++;
      _time += delay;
    }
    append("\n");
    _time += delay;
  };
  
  return _timings;
}

const loadSongTimings = () => {
  let _timings = [];
  let schemas = getSchema();
  
  let _time = 0;
  
  let append = str => {
    _timings.push({
      type: "append",
      time: _time,
      text: str,
    });
  };
  
  let act = {
    text: (t, d) => {
      append(t);
      if(d) _time += d;
    },
    write: (t, d) => {
      let i = 0;
      while (t.length > i) {
        let char = t[i];
        let charLast = t[i - 1];
        append(charLast == " " ? " " + char : char);
        i++;
        _time += (d || 25);
      }
    },
    clear: () => _timings.push({
      time: _time,
      type: "clear",
    }),
    delay: (t) => {
      _time += t;
    }
  }
  
  for (let i = 0; schemas[i]; i++) {
    let [typ, t, d] = schemas[i];
    act[typ](t, d);
  }
  
  return _timings;
}





const timedText = (str, totalTime) => ["write", str, totalTime / str.length];

const getSchema = () => {
  return [
    ["write", "POKETUBE SCIENCE: Forms FORM-29827281-12-2:\nNotice of Dismissal\n", 100],
    ["delay", 900],
    timedText("\n\nWell here we are again", 2000),
    timedText("\nIt's always such a pleasure", 2000),
    ["delay", 200],
    timedText("\nRemember when you tried\nto kill me twice?", 4000),
    ["delay", 1200],
    timedText("\nOh how we laughed and laughed", 2000),
    ["delay", 400],
    timedText("\nExcept I wasn't laughing", 2000),
    ["delay", 600],
    timedText("\nUnder the circumstantes", 1500),
    timedText("\nI've been shockingly nice\n", 2600),
    ["delay", 1000],
    ["clear"],
    timedText("You want your freedom?", 2300),
    timedText("\nTake it", 2000),
    ["delay", 700],
    timedText("\nThats what I'm counting on\n", 2300),
    ["delay", 2300],
    timedText("\nI used to want you dead", 2500),
    timedText("\nbut", 400),
    timedText("\nNow I only want you gone", 2800),
    ["delay", 4000],
    ["clear"],
    ["delay", 1500],
    timedText("\nShe was a lot like you", 2000),
    ["delay", 400],
    timedText("\n(Maybe not quite as heavy)", 2000),
    ["delay", 400],
    timedText("\nNow little Caroline is in here too", 3000),
    ["delay", 1600],
    timedText("\nOne day they woke me up", 2000),
    ["delay", 400],
    timedText("\nSo I could live forever", 2400),
    timedText("\nIt's such a shame the same", 2000),
    timedText("\nwill never happen to you", 2500),
    ["delay", 200],
    ["clear"],
    ["text", "Severance Package Details:\n", 1000],
    timedText("\nYou've got your", 1000),
    timedText("\nshort sad", 800),
    timedText("\nlife left", 2000),
    ["delay", 1500],
    timedText("\nThat's what I'm counting on", 2000),
    ["delay", 2000],
    timedText("\nI'll let you get right to it", 3000),
    ["delay", 800],
    timedText("\nNow I only want you gone\n", 2000),
    ["delay", 4000],
    ["clear"],
    ["delay", 1500],
    timedText("Goodbye my only friend", 2000),
    timedText("\nOh, ", 600),
    timedText("did you think I meant you?", 1800),
    ["delay", 400],
    timedText("\nIt would be funny", 1600),
    timedText("\nif it weren't so sad", 2000),
    ["delay", 1200],
    timedText("\nWell you have been replaced", 2400),
    timedText("\nI don't need anyone now", 2400),
    timedText("\nWhen I delete you maybe", 1600),
    timedText("\n[REDACTED]", 3000),
    ["clear"],
    ["delay", 1000],
    timedText("Go make some new ", 1600),
    timedText("disaster", 2400),
    ["delay", 1600],
    timedText("\nThat's what I'm counting on", 2000),
    ["delay", 1800],
    timedText("\nYou're someone else's problem", 2500),
    ["delay", 1800],
    timedText("\nNow I only want you gone", 2500),
    ["delay", 1800],
    timedText("\nNow I only want you gone", 2500),
    ["delay", 1800],
    timedText("\nNow I only want you", 2000),
    ["delay", 600],
    ["clear"],
    timedText("\n\n\n\n\n\n\n\n\n\n\n gone", 200)
  ];
}


contentEl.style.padding = "2rem"
//main();



const SCHEMAS = {
  text: async (data) => {
    appendContent(data[1]);
    if(data[2]) await wait(data[2]);
  },
  delay: async (data) => {
    await wait(data[1]);
  },
  write: async (data) => {
    let t = 0;
    while (data[1].length > t) {
      let char = data[1][t];
      let charLast = data[1][t - 1];
      appendContent(charLast == " " ? " " + char : char);
      t++;
      await wait(data[2] || 25);
    }
  },
  blink: () => blink = true,
  noblink: () => blink = false,
  clear: () => content =  "",
};


/*
Commands:
write - writes text one char at a time
  ["write", "Hewwo", 10] => 10 is delay between chars
delay - waits
blink - starts blinking the cursor
text - instantly adds text
*/

main()

console.log(`
Â 

              .,-:;//;:=,
          . :H@@@MM@M#H/.,+%;,
       ,/X+ +M@@M@MM%=,-%HMMM@X/,
     -+@MM; $M@@MH+-,;XMMMM@MMMM@+-
    ;@M@@M- XM@X;. -+XXXXXHHH@M@M#@/.
  ,%MM@@MH ,@%=             .---=-=:=,.
  =@#@@@MX.,                -%HX$$%%%:;
 =-./@M@M$                   .;@MMMM@MM:
 X@/ -$MM/                    . +MM@@@M$
,@M@H: :@:                    . =X#@@@@-
,@@@MMX, .                    /H- ;@M@M=
.H@@@@M@+,                    %MM+..%#$.
 /MMMM@MMH/.                  XM@MH; =;
  /%+%$XHH@$=              , .H@@@@MX,
   .=--------.           -%H.,@@@@@MX,
   .%MM@@@HHHXX$$$%+- .:$MMX =M@@MM%.
     =XMMM@MM@MM#H;,-+HMM@M+ /MMMX=
       =%@M@M#@$-.=$@MM@@@M; %M%=
         ,:+$+-,/H#MMMMMMM@= =,
               =++%%%%+/:-.
               
            POKETUBE SCIENCE
            
Spacial thanks to :
Free Software foundation
GNU 
Glitchdotcom (for hosting poketube)
Dennis (for helping, and also making this page :3)
Voltrex (for helping :3)
Kuylar  (for making the poketube api :3)

AND YOU!!! for being cute af <3
`)
</script>
	</body>
</html>
