add skedul
All checks were successful
Swaous.Asuscomm Build / Build-Docker-Image (push) Successful in 27s
All checks were successful
Swaous.Asuscomm Build / Build-Docker-Image (push) Successful in 27s
This commit is contained in:
1
skedul/.gitignore
vendored
Normal file
1
skedul/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
data.json
|
||||||
36
skedul/README
Normal file
36
skedul/README
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
very simple customized class schedules applet. to use it, create a data.json file in the project root and put all the files in the static directory of your webserver!
|
||||||
|
|
||||||
|
features
|
||||||
|
* shows first, next, and last classes for the day
|
||||||
|
* shows all your classes for the week on a grid
|
||||||
|
* configure links for class buildings (google maps or whatever)
|
||||||
|
|
||||||
|
data.json is structured like so:
|
||||||
|
{
|
||||||
|
"year": 2025,
|
||||||
|
"semester": "Semester", // spring, fall, whatever
|
||||||
|
"credits": 30, // your class credits this semester [purely cosmetic]
|
||||||
|
"maps": {
|
||||||
|
"building name": "link to the building in google maps or whatever"
|
||||||
|
},
|
||||||
|
"week": [
|
||||||
|
{
|
||||||
|
"days": [1, 3, 5], // 1 is monday, 2 is tuesday, etc. weekend courses currently aren't supported.
|
||||||
|
"start_time": 1100, // 24-hour timestamps.
|
||||||
|
"end_time": 1215,
|
||||||
|
"name": "Physics",
|
||||||
|
"type": "Lecture", // options are Lecture, Lab, Studio, Class, and Test.
|
||||||
|
"building": "The Bestest Building", // must be exactly the same as the building name in `maps` for the links to work
|
||||||
|
"room": "101" // your room in the building
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"days": [2, 4],
|
||||||
|
"start_time": 1230,
|
||||||
|
"end_time": 1515,
|
||||||
|
"name": "Chemistry",
|
||||||
|
"type": "Lab",
|
||||||
|
"building": "Laboratorium!",
|
||||||
|
"room": "66"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
43
skedul/index.html
Normal file
43
skedul/index.html
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tyler's Course Schedule</title>
|
||||||
|
<link rel="stylesheet" href="main.css" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1"
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="topline">
|
||||||
|
<div>
|
||||||
|
<span id="semester"></span> <span id="year"></span>
|
||||||
|
<p style="font-size: 0.7em; color: lightgrey;"><span id="credits"></span> credits</p>
|
||||||
|
</div>
|
||||||
|
<div id="firstclass">
|
||||||
|
<b>FIRST CLASS</b><br>
|
||||||
|
<a class="bloc"><span class="cname"></span> <span class="ctype"></span> at <span class="building"></span> <span class="room"></span> from <span class="start"></span> to <span class="end"></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="nextclass">
|
||||||
|
<b>NEXT CLASS</b><br>
|
||||||
|
<a class="bloc"><span class="cname"></span> <span class="ctype"></span> at <span class="building"></span> <span class="room"></span> from <span class="start"></span> to <span class="end"></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="lastclass">
|
||||||
|
<b>LAST CLASS</b><br>
|
||||||
|
<a class="bloc"><span class="cname"></span> <span class="ctype"></span> at <span class="building"></span> <span class="room"></span> from <span class="start"></span> to <span class="end"></span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table id="schedule">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>Monday</td>
|
||||||
|
<td>Tuesday</td>
|
||||||
|
<td>Wednesday</td>
|
||||||
|
<td>Thursday</td>
|
||||||
|
<td>Friday</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
121
skedul/main.css
Normal file
121
skedul/main.css
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
#topline {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: rgb(0, 51, 68);
|
||||||
|
color: white;
|
||||||
|
font-family: monospace;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topline > * {
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topline a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#firstclass {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#schedule>tbody td:first-child {
|
||||||
|
font-size: 0.7em;
|
||||||
|
color: transparent;
|
||||||
|
position: relative;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:first-child>span {
|
||||||
|
position: absolute;
|
||||||
|
top: -0.7em;
|
||||||
|
left: 0px;
|
||||||
|
background-color: white;
|
||||||
|
width: auto;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead td {
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:not(:first-child) {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
border-top: 1px solid rgb(167, 167, 167);
|
||||||
|
position: relative;
|
||||||
|
height: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coursename {
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coursetype {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:not(:first-child) {
|
||||||
|
vertical-align: top;
|
||||||
|
font-family: monospace;
|
||||||
|
padding: 4px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.Lecture {
|
||||||
|
background-color: rgb(255, 207, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
td.Lab {
|
||||||
|
background-color: lightblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.Class {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.Studio {
|
||||||
|
background-color: lightgreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.Test {
|
||||||
|
background-color: red;
|
||||||
|
box-shadow: 0px 0px 20px 10px rgb(88, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.youarehere {
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youarehere::after{
|
||||||
|
font-weight: bold;
|
||||||
|
content: 'you are HERE!';
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:1000px) {
|
||||||
|
td {
|
||||||
|
font-size: 0.5em !important;
|
||||||
|
}
|
||||||
|
#topline {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#topline > * {
|
||||||
|
margin: 20px !important;
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
height: 0.7em;
|
||||||
|
}
|
||||||
|
}
|
||||||
104
skedul/main.js
Normal file
104
skedul/main.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
function tohours(mns) { // convert a value in minutes to a 24-hour timestamp, e.g. 330 -> 0530
|
||||||
|
let hour = Math.floor(mns / 60);
|
||||||
|
let minute = mns % 60;
|
||||||
|
return hour * 100 + minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tomins(hrs) { // convert a value in 24-hour to minutes, the inverse of tohours
|
||||||
|
let hour = Math.floor(hrs / 100);
|
||||||
|
let minute = hrs % 100;
|
||||||
|
return hour * 60 + minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
const daystart = tomins(1000);
|
||||||
|
|
||||||
|
function zpad(thing, zeroes) { // left-pad a string with zeroes
|
||||||
|
thing = "" + thing;
|
||||||
|
while (thing.length < zeroes) {
|
||||||
|
thing = "0" + thing;
|
||||||
|
}
|
||||||
|
return thing;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tonicehrs(hrs) { // convert a value in 24-hour to a string (800 -> "08:00", 1645 -> "16:45")
|
||||||
|
let hour = Math.floor(hrs / 100);
|
||||||
|
if (hour > 12) {
|
||||||
|
hour -= 12;
|
||||||
|
}
|
||||||
|
let minute = hrs % 100;
|
||||||
|
return zpad(hour, 2) + ":" + zpad(minute, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tablesetup() {
|
||||||
|
for (var i = 0; i < 11 * 4; i ++) {
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
let time = tonicehrs(tohours(daystart + i * 15))
|
||||||
|
row.innerHTML = `<td>${time}<span>${time}</span></td><td></td><td></td><td></td><td></td><td></td>`;
|
||||||
|
document.querySelector("#schedule > tbody").appendChild(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setClassTo(el, c, map) {
|
||||||
|
el.querySelector(".cname").innerText = c.name;
|
||||||
|
el.querySelector(".ctype").innerText = c.type;
|
||||||
|
el.querySelector(".bloc").href = map[c.building];
|
||||||
|
el.querySelector(".building").innerText = c.building;
|
||||||
|
el.querySelector(".room").innerText = c.room;
|
||||||
|
el.querySelector(".start").innerText = tonicehrs(c.start_time);
|
||||||
|
el.querySelector(".end").innerText = tonicehrs(c.end_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
window.addEventListener("load", async () => {
|
||||||
|
let data = await (await fetch("data.json")).json();
|
||||||
|
document.getElementById("year").innerHTML = data.year;
|
||||||
|
document.getElementById("semester").innerHTML = data.semester;
|
||||||
|
document.getElementById("credits").innerHTML = data.credits;
|
||||||
|
tablesetup();
|
||||||
|
let tbody = document.querySelector("#schedule > tbody")
|
||||||
|
let curday = new Date().getDay();
|
||||||
|
let firstClass = undefined;
|
||||||
|
let nextClass = undefined;
|
||||||
|
let lastClass = undefined;
|
||||||
|
let now = new Date();
|
||||||
|
let curTime = now.getMinutes() + now.getHours() * 100;
|
||||||
|
let curTimeSnap = Math.round((tomins(curTime) - daystart) / 15);
|
||||||
|
tbody.children[curTimeSnap].children[curday].classList.add("youarehere");
|
||||||
|
for (let cls of data.week) {
|
||||||
|
for (let day of cls.days) {
|
||||||
|
if (day == curday) {
|
||||||
|
if (firstClass == undefined || cls.start_time < firstClass.start_time) {
|
||||||
|
firstClass = cls;
|
||||||
|
}
|
||||||
|
if (lastClass == undefined || cls.end_time > lastClass.end_time) {
|
||||||
|
lastClass = cls;
|
||||||
|
}
|
||||||
|
if (cls.start_time > curTime) {
|
||||||
|
if (nextClass == undefined || cls.start_time < nextClass.start_time) {
|
||||||
|
nextClass = cls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let start = Math.floor((tomins(cls.start_time) - daystart) / 15);
|
||||||
|
let el = tbody.children[start].children[day];
|
||||||
|
el.classList.add("class");
|
||||||
|
let rows = Math.floor((tomins(cls.end_time) - tomins(cls.start_time)) / 15);
|
||||||
|
el.rowSpan = rows;
|
||||||
|
for (var i = start + 1; i < start + rows; i ++) { // cull the tds that this td is overlapping
|
||||||
|
tbody.children[i].removeChild(tbody.children[i].children[day]);
|
||||||
|
}
|
||||||
|
el.classList.add(cls.type);
|
||||||
|
el.innerHTML = `<span class="coursename">${cls.name}</span><span class="coursetype">${cls.type}</span> at <a href="${data.maps[cls.building]}" about="blank">${cls.building}</a> ${cls.room}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstClass) {
|
||||||
|
setClassTo(document.getElementById("firstclass"), firstClass, data.maps);
|
||||||
|
}
|
||||||
|
if (nextClass) {
|
||||||
|
setClassTo(document.getElementById("nextclass"), nextClass, data.maps);
|
||||||
|
}
|
||||||
|
if (lastClass) {
|
||||||
|
setClassTo(document.getElementById("lastclass"), lastClass, data.maps);
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user