-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
programming.html
329 lines (294 loc) · 14.7 KB
/
programming.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link rel="icon" href="/favicon.png" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/iphone-icon.png">
<link rel="manifest" href="/manifest.json">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> <link href="styles.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi" crossorigin="anonymous"></script>
<link href="styles.css" rel="stylesheet">
<link href="prism.css" rel="stylesheet">
<title>Programming</title>
</head>
<body>
<main class="transparentBG fade-to-black">
<header class="header-color">
<video class="img-fluid mx-auto" autobuffer="true" autoplay playsinline loop muted style="display:block;">
<source src="video/Banner-HEVC.mov" type="video/mp4; codecs=hvc1">
<source src="video/Banner-VP9.webm" type="video/webm">
Your browser does not support the video tag.
</video>
</header>
<div class="horizontal-line d-md-none"></div>
<nav class="navbar navbar-expand-lg navbar-dark bg-gradient responsive-padding" style="background-color: #325A80;">
<a class="navbar-brand brand-margin hide-on-desktop" style="color: #FFFFFF" href="index.html">Paul Thompson | Software Engineer</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav responsive-padding">
<a class="nav-link" href="index.html">Home</a>
<a class="nav-link" href="interactive-art.html">Interactive Art</a>
<a class="nav-link active" aria-current="page" href="programming.html">Programming</a>
<a class="nav-link" href="coding-streams.html">Coding Streams</a>
<a class="nav-link" href="contact.html">Contact Me</a>
</div>
</div>
</nav>
<div class ="content">
<div class="responsive-margin">
<h3><b>No Concessions</b></h3>
<p>I recently deployed a web application called <a class="link" href="http://noconcessions.xyz" target="_blank" rel="noopener noreferrer">No Concessions</a> that allows users to find new movies based on shared taste with other users.</p>
<p>The application was built with React, TypeScript, Express, Tailwind, PostgreSQL, and Docker.</p>
<br>
<h3><b>Finding Focus Comic Strip</b></h3>
<p>I host my comics on my art website <a class="link" href="https://findingfocus.art" target="_blank" rel="noopener noreferrer">findingfocus.art</a></p>
<p>The site is built using React, TypeScript, Tailwind, and Nginx. I have over 200 more comics still needing to be exported and added to the site.</p>
<br>
<h3><b>Bitrate Calculator</b></h3>
Enter the duration and filesize of a video to calculate its bitrate with this web application.
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#check').addEventListener('click', function() {
let hourString = "Hours ";
let minuteString = "Minutes ";
let secondString = "Seconds ";
let filesizeString = "Bitrate is about: ";
let hours = hourInput.value;
let minutes = minuteInput.value;
let seconds = secondInput.value;
let totalSeconds = (hours * 3600) + (minutes * 60) + (seconds * 1);
let megabits = filesizeInput.value * 8;
let answer = megabits / totalSeconds;
answer = answer.toFixed(2);
if (isNaN(answer)) {
answer = Number(0);
}
//document.querySelector('#hourI').innerHTML = hourString.concat(hourInput.value);
//document.querySelector('#minuteI').innerHTML = minuteString.concat(minuteInput.value);
//document.querySelector('#secondI').innerHTML = secondString.concat(secondInput.value);
document.querySelector('#filesizeI').innerHTML = filesizeString.concat(answer, "Mbps");
event.preventDefault();
});
});
</script>
<div id="duration" style="margin-top: 5px;">
<label>Hours</label>
<input type="number" autocomplete="off" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" id="hourInput" min="0" max="99" value="" maxlength="2" style="width: 60px">
<label>Minutes</label>
<input type="number" autocomplete="off" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" id="minuteInput" min="0" max="60" value="" maxlength="2" style="width: 60px">
<label>Seconds</label>
<input type="number" autocomplete="off" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" id="secondInput" min="0" max="60" value="" maxlength="2" style="width: 60px; margin-top:5px;">
<br>
<label>Filesize (megabytes)</label>
<input type="number" autocomplete="off" onkeypress="return isNumeric(event)" oninput="maxLengthCheck(this)" id="filesizeInput" min="0" max="999999" maxlength="6" value="" style="width: 100px; margin-top: 10px;">
<br>
<a class="btn btn-primary bg-gradient" id="check" role="button" style="margin-top: 10px;">Calculate Bitrate</a>
<script>
function maxLengthCheck(object) {
if (object.value.length > object.maxLength)
object.value = object.value.slice(0, object.maxLength)
}
function isNumeric (evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode (key);
var regex = /[0-9]|\./;
if ( !regex.test(key) ) {
theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault();
}
}
</script>
</div>
<div id="hourI">
</div>
<div id="minuteI">
</div>
<div id="secondI">
</div>
<u>
<div id="filesizeI" style="margin-top: 15px;">
</div>
</u>
</div>
<br>
<div class="responsive-margin">
<h3><b>Python Programming</b></h3>
<div class="box" style="margin-left:0px; margin-right:0px;">
<pre style="font-size: 16px">
<code class="language-py">
# This app generates .docx files and zips them for video deposition preparation
# Currently deployed to the web at trattel.xyz
from docxtpl import DocxTemplate
import os
import zipfile
from datetime import datetime
import shutil
OUTPUT_FOLDER = "Output"
def clear_output_folder(folder_path):
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
except Exception as e:
print(f'Failed to delete {file_path}. Reason: {e}')
def perform_task(year, videographer, month_str, day, start_time, deponent, case_name, plaintiff_attorney, defense_attorney):
# Convert month to integer and validate
try:
month = int(month_str)
if month < 1 or month > 12:
raise ValueError("Month must be between 1 and 12.")
except ValueError as e:
return str(e), None
month_text = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][month - 1]
def get_day_suffix(day):
if 10 <= day <= 20:
return 'th'
last_digit = day % 10
return {1: 'st', 2: 'nd', 3: 'rd'}.get(last_digit, 'th')
try:
day = int(day)
if day < 1 or day > 31:
raise ValueError("Day must be between 1 and 31.")
except ValueError as e:
return str(e), None
day_suffix = get_day_suffix(day)
# Clear the output folder before generating new files
clear_output_folder(OUTPUT_FOLDER)
# Define file paths
date_str = f"{year}-{month:02}-{day:02}"
readon_path = f"{OUTPUT_FOLDER}/READON {deponent} {month}-{day}-{year}.docx"
videolog_path = f"{OUTPUT_FOLDER}/{deponent} {month}-{day}-{year}.docx"
zip_filename = f"{OUTPUT_FOLDER}/{date_str} {deponent} Video Worksheets.zip"
# Create Output directory if it doesn't exist
os.makedirs(os.path.dirname(readon_path), exist_ok=True)
# Create and save .docx files
try:
subject_line = f"{month}-{day}-{year} {deponent} Deposition"
doc = DocxTemplate("readonTemplate.docx")
context = {
'year': year,
'videographer': videographer,
'month': month_text,
'day': day,
'suffix': day_suffix,
'start_time': start_time,
'deponent': deponent,
'case_name': case_name,
'plaintiff_attorney': plaintiff_attorney,
'defense_attorney': defense_attorney,
'subject_line': subject_line
}
doc.render(context)
doc.save(readon_path)
# Use videologTemplate
videolog_template_path = "videologTemplate.docx"
doc = DocxTemplate(videolog_template_path)
doc.render(context)
doc.save(videolog_path)
# Create the ZIP file
with zipfile.ZipFile(zip_filename, 'w') as zipf:
zipf.write(readon_path, os.path.basename(readon_path))
zipf.write(videolog_path, os.path.basename(videolog_path))
except Exception as e:
return f"Error generating files: {e}", None
return zip_filename, None
</code>
</pre>
<br>
<h3><b>Sonic Pi Programming</b></h3>
<pre style="font-size: 16px">
<code class="language-python">
# Music for my programming streams
with_fx :reverb do
live_loop :kick do
sample :drum_heavy_kick, rate: 0.5, amp: 0.5
sleep 8
end
live_loop :hihats do
sample :drum_tom_hi_soft, rate: 1, amp: 0.3
sleep 1
end
live_loop :guitar do
sample :guit_em9, rate: 0.5, amp: 0.3
sleep 16
end
end
use_synth :hollow
with_fx :reverb, mix: 1 do
live_loop :note1 do
play choose([:E4,:B5]), attack: 6, release: 6
sleep 8
end
live_loop :note2 do
play choose([:G4,:D5]), attack: 4, release: 5
sleep 10
end
live_loop :note3 do
play choose([:A5, :Fs4]), attack: 5, release: 5
sleep 11
end
end
</code>
</pre>
<br>
<h3><b>Artist's Prayer in C</b></h3>
<pre style="font-size: 16px">
<code class="language-c">
#include <stdio.h>
#define LINES 25
const char *Prayer[LINES];
int main()
{
printf("%s\n", Prayer[0]);
char input;
for (int i = 1; i < LINES; i++)
{
scanf("%c", &input);
if (input == 10)
{
printf("%s\n", Prayer[i]);
}
}
}
const char *Prayer[] = {
"O Great Muse",
"Gift us with your presence",
"And we shall commit to the work of showing up",
"Let us handle the quantity, and you handle the quality",
"Help us love ourselves so we can love others",
"Help us grow so we can help others grow",
"Please alert us when we are on the wrong path",
"By showing us interesting new directions to follow",
"Let us not get wrapped up in the end product, but in the process itself",
"Help us love the present and work out of it not for an imaginary future",
"But to make art for its own sake and its own beauty",
"Grant us the courage to try, and the confidence for having done so",
"Help us unite with other creators so we can encourage each other",
"If we are depressed, help us cling to what is beautiful in the moment",
"And help nudge us towards contentment even in difficult times",
"We promise to offer our work to you consistently",
"And we will listen to where our hearts tell us to go",
"We dedicate our creations to you and they do not belong to us",
"For we were only gifted the idea through the ether",
"And we are merely forging it and returning it to the universe",
"Allow us to realize we all deserve love",
"And that we are all the same divine light",
"We cannot be alone when we realize this",
"We create in honor of each other's divinity",
"Please accept our gifts as they are only made possible through your grace"
};
</code>
</pre>
<br>
</main>
<script src="prism.js"></script>
</body>
</html>