first commit
commit
646e3d51a3
@ -0,0 +1,4 @@
|
||||
db/
|
||||
**/__pycache__/
|
||||
media/
|
||||
venv/
|
@ -0,0 +1,27 @@
|
||||
How does 2bitcharactergenerator actually work?
|
||||
|
||||
Let's make all the canvas elements visible...
|
||||
|
||||
The stylesheet sets "image-rendering: pixelated" on the canvas element, which seems to be supported on contemporary Firefox + Chrome. The elements have width and height attributes set to 16, while their height in CSS is set to 64px producing a (pixelated) scaling up. However the actual size in the canvas coordinates remains unscaled.
|
||||
|
||||
This makes caption generation in the canvas tricky.
|
||||
|
||||
https://developer.mozilla.org/en-US/docs/Games/Techniques/Crisp_pixel_art_look
|
||||
|
||||
diggin into the history of workadventure
|
||||
|
||||
https://web.archive.org/web/20210623060444/https://thecodingmachine.io/energy-consumption-web-game-engine
|
||||
|
||||
https://medium.com/@michaelwesthadley/modular-game-worlds-in-phaser-3-tilemaps-1-958fc7e6bbd6
|
||||
|
||||
https://docs.phaser.io/api-documentation/class/tilemaps-tilemap
|
||||
|
||||
FOCUS
|
||||
* CALL as good self-contained page.
|
||||
* POST -> LINK to "visit (rp)guestbook"
|
||||
* ANIMATION GENERATOR... (for mail/masto/IG)
|
||||
|
||||
"I want to be"
|
||||
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Creature
|
||||
|
||||
admin.site.register(Creature)
|
@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CallConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'call'
|
@ -0,0 +1,14 @@
|
||||
from django.forms import ModelForm
|
||||
from call.models import Creature
|
||||
|
||||
|
||||
class CreatureForm(ModelForm):
|
||||
class Meta:
|
||||
model = Creature
|
||||
fields = ["image", "caption", "message"]
|
||||
|
||||
class CreatureFormNoImage(ModelForm):
|
||||
class Meta:
|
||||
model = Creature
|
||||
fields = ["caption", "message"]
|
||||
|
@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.1.5 on 2025-01-21 07:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Creature',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('image', models.ImageField(upload_to='creatures')),
|
||||
('caption', models.CharField(max_length=255)),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='date created')),
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='date updated')),
|
||||
('message', models.TextField(max_length=512)),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.5 on 2025-01-21 07:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('call', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='creature',
|
||||
name='message',
|
||||
field=models.TextField(blank=True, max_length=512),
|
||||
),
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Creature(models.Model):
|
||||
image = models.ImageField(upload_to="creatures")
|
||||
caption = models.CharField(max_length=255)
|
||||
created = models.DateTimeField("date created", auto_now_add=True)
|
||||
updated = models.DateTimeField("date updated", auto_now=True)
|
||||
message = models.TextField(max_length=512, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-created"]
|
@ -0,0 +1,395 @@
|
||||
var PARTS_MAX = {
|
||||
eyes: 12,
|
||||
mouth: 8,
|
||||
ears: 6,
|
||||
torso: 5,
|
||||
hair: 22,
|
||||
};
|
||||
var gParts = {}
|
||||
var gColor = 0;
|
||||
var gColorMode = '012';
|
||||
|
||||
var showCanvas = document.getElementById('c');
|
||||
|
||||
var outCanvas = document.getElementById('outc');
|
||||
outCanvas.width = 16 * 6;
|
||||
outCanvas.height = 16 * 1;
|
||||
|
||||
|
||||
var ctx = showCanvas.getContext('2d');
|
||||
var outCtx = outCanvas.getContext('2d');
|
||||
|
||||
var outCanvas_gbs_s = document.getElementById("outc_gbs_s")
|
||||
outCanvas_gbs_s.width = 48
|
||||
outCanvas_gbs_s.height = 16
|
||||
|
||||
var outCanvas_gbs_a = document.getElementById("outc_gbs_a")
|
||||
outCanvas_gbs_a.width = 96
|
||||
outCanvas_gbs_a.height = 16
|
||||
|
||||
var outCtx_gbs_s = outCanvas_gbs_s.getContext('2d');
|
||||
var outCtx_gbs_a = outCanvas_gbs_a.getContext('2d');
|
||||
|
||||
var a = function(n) {
|
||||
return n
|
||||
.split(',')
|
||||
.map(function(k){ return { x: parseInt(k), f: !!k.match('f')} });
|
||||
}
|
||||
var ANIMS = {
|
||||
stand: a("0"),
|
||||
rotate: a("0,2f,1,2"),
|
||||
run_front: a("0,3,0f,3f"),
|
||||
run_back: a("1,4,1f,4f"),
|
||||
run_left: a("2,5"),
|
||||
run_right: a("2f,5f"),
|
||||
}
|
||||
var ANIM_NAMES = Object.keys(ANIMS);
|
||||
var currentAnimName = "stand";
|
||||
|
||||
var gTextures = { loaded: 0, requested: 0 };
|
||||
|
||||
loadAllTextures();
|
||||
|
||||
var __appstarted = false;
|
||||
function loadTexture(key) {
|
||||
// var tex = new Image();
|
||||
var tex = document.querySelector("#all_imgs").querySelector('#img_'+key);
|
||||
|
||||
// tex.src = "./" + key + ".png?v=" + Math.random();
|
||||
gTextures.requested++;
|
||||
gTextures[key] = tex;
|
||||
|
||||
var tex_onload = function() {
|
||||
gTextures.loaded++;
|
||||
if(gTextures.loaded === gTextures.requested){
|
||||
if(__appstarted){
|
||||
updateOutCanvas();
|
||||
} else {
|
||||
startApp();
|
||||
}
|
||||
} else {
|
||||
document.getElementById('loading').innerText =
|
||||
"loading... " + gTextures.loaded + " / " + gTextures.requested;
|
||||
}
|
||||
}
|
||||
|
||||
if (tex.complete) {
|
||||
window.setTimeout(tex_onload, 10);
|
||||
} else {
|
||||
tex.onload = tex_onload;
|
||||
}
|
||||
}
|
||||
|
||||
function loadAllTextures() {
|
||||
loadTexture("hair");
|
||||
loadTexture("base");
|
||||
loadTexture("eyes");
|
||||
loadTexture("mouth");
|
||||
loadTexture("ears");
|
||||
loadTexture("torso");
|
||||
loadTexture("hands");
|
||||
}
|
||||
|
||||
function startApp() {
|
||||
__appstarted = true;
|
||||
setupInput("eyes")
|
||||
setupInput("mouth")
|
||||
setupInput("ears")
|
||||
setupInput("torso")
|
||||
setupInput("hair")
|
||||
setupColorInput();
|
||||
setupColorMode();
|
||||
|
||||
updateOutCanvas();
|
||||
updateAnimBtnText();
|
||||
window.setInterval(animate, 16);
|
||||
|
||||
document.getElementById('loading').innerText = '';
|
||||
document.getElementById('root').className = '';
|
||||
}
|
||||
|
||||
function animate(){
|
||||
ctx.clearRect(0, 0, 16, 16);
|
||||
var t = Date.now ? Date.now() : +(new Date());
|
||||
|
||||
var nt = parseInt(t / 200)
|
||||
var anim = ANIMS[currentAnimName];
|
||||
var len = anim.length;
|
||||
|
||||
var findex = nt % len;
|
||||
var frame = anim[findex];
|
||||
|
||||
ctx.save();
|
||||
if(frame.f){
|
||||
ctx.translate(16, 0);
|
||||
ctx.scale(-1, 1);
|
||||
}
|
||||
ctx.drawImage(outCanvas, frame.x * 16, 0, 16, 16, 0, 0, 16, 16);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
|
||||
var animbtn = document.getElementById('animbtn');
|
||||
function updateAnimBtnText(){
|
||||
animbtn.innerText = currentAnimName.replace("_", " ");
|
||||
}
|
||||
animbtn.onclick = function() {
|
||||
var index = ANIM_NAMES.indexOf(currentAnimName);
|
||||
currentAnimName = ANIM_NAMES[index + 1] || ANIM_NAMES[0];
|
||||
updateAnimBtnText();
|
||||
}
|
||||
showCanvas.onclick = animbtn.onclick;
|
||||
|
||||
// var randomizebtn = document.getElementById('randomizebtn');
|
||||
// randomizebtn.onclick = function() {
|
||||
// var inputs = document.getElementById('inputs').querySelectorAll('input');
|
||||
|
||||
// for(var i=0; i<inputs.length; i++){
|
||||
// var input = inputs[i];
|
||||
|
||||
// var key = input.id.replace("Input", "");
|
||||
// var max = PARTS_MAX[key];
|
||||
// var randval = Math.floor(Math.random() * (max + 1));
|
||||
// input.value = randval;
|
||||
// gParts[key] = randval;
|
||||
// }
|
||||
|
||||
// updateOutCanvas();
|
||||
// }
|
||||
|
||||
// 13 * 9 * 7 * 6 * 23 = 113'022
|
||||
|
||||
var COLORS = [
|
||||
["#000000", "#787878", "#e8e8e8", "#ffffff", "Basic"],
|
||||
["#071821", "#86c06c", "#e0f8cf", "#65ff00", "GBS"],
|
||||
["#7c3f58", "#eb6b6f", "#f9a875", "#fff6d3", "ICE CREAM GB PALETTE by Kerrie Lake"],
|
||||
["#2d1b00", "#1e606e", "#5ab9a8", "#c4f0c2", "MIST GB PALETTE by Kerrie Lake"],
|
||||
["#2c2137", "#764462", "#edb4a1", "#a96868", "RUSTIC GB PALETTE by Kerrie Lake"],
|
||||
["#20283d", "#426e5d", "#e5b083", "#fbf7f3", "EN4 PALETTE by ENDESGA"],
|
||||
["#4c1c2d", "#d23c4e", "#5fb1f5", "#eaf5fa", "GRAND DAD 4 PALETTE by Starlane"],
|
||||
[ "#181010", "#84739c", "#f7b58c", "#ffefff", "POKEMON (SGB) PALETTE" ],
|
||||
[ "#2b2b26", "#706b66", "#a89f94", "#e0dbcd", "GRAFXKID GAMEBOY POCKET (GRAY) PALETTE by GrafxKid" ],
|
||||
[ "#000000", "#ff55ff", "#55ffff", "#ffffff", "CGA PALETTE 1 (HIGH) PALETTE" ],
|
||||
[ "#243137", "#3f503f", "#768448", "#acb56b", "NINTENDO GAMEBOY (ARNE) PALETTE by Arne" ],
|
||||
[ "#260016", "#ed008c", "#00bff3", "#daf3ec", "JB4 PALETTE by Haretro for his game Jet Boy" ],
|
||||
[ "#253b46", "#18865f", "#61d162", "#ebe7ad", "SWEET GUARANÁ PALETTE by MadPezkoh" ],
|
||||
[ "#4c625a", "#7b9278", "#abc396", "#dbf4b4", "GRAFXKID GAMEBOY POCKET (GREEN) PALETTE by GrafxKid" ],
|
||||
];
|
||||
|
||||
function drawPart(key, forceY, forceFrame){
|
||||
var y = gParts[key] == null ? forceY : gParts[key]; // 0's falsy
|
||||
if(y == null){ return }
|
||||
var w = 16 * 6;
|
||||
var h = 16;
|
||||
|
||||
|
||||
if(forceFrame || forceFrame === 0){
|
||||
outCtx.drawImage(gTextures[key], forceFrame*16, y*16, 16, 16, forceFrame*16, 0, 16, 16);
|
||||
} else {
|
||||
outCtx.drawImage(gTextures[key], 0, y*16, w, h, 0, 0, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function GBS_recolor_fn()
|
||||
{
|
||||
return {
|
||||
dark: parseColorStr("#071821"),
|
||||
mid: parseColorStr("#86c06c"),
|
||||
light: parseColorStr("#e0f8cf"),
|
||||
bg: parseColorStr("#65ff00"),
|
||||
}
|
||||
}
|
||||
|
||||
function GBS_recolor(ctx, w)
|
||||
{
|
||||
var imageData = ctx.getImageData(0, 0, w || 96, 16);
|
||||
recolor(imageData.data, GBS_recolor_fn);
|
||||
ctx.putImageData(imageData,0,0);
|
||||
}
|
||||
|
||||
function ff(ctx, src, f, sx, sy, dx)
|
||||
{
|
||||
f && ctx.save();
|
||||
f && ctx.scale(-1, 1);
|
||||
ctx.drawImage(src, 16*sx, sy*16, 16, 16, dx*16, 0, 16, 16);
|
||||
f && ctx.restore();
|
||||
}
|
||||
|
||||
var FLIP = true;
|
||||
|
||||
function updateGBS()
|
||||
{
|
||||
ff(outCtx_gbs_s, outCanvas, null, 0, 0, 0);
|
||||
ff(outCtx_gbs_s, outCanvas, null, 1, 0, 1);
|
||||
ff(outCtx_gbs_s, outCanvas, FLIP, 2, 0, -3);
|
||||
|
||||
GBS_recolor(outCtx_gbs_s, 48);
|
||||
|
||||
updateExportLink("export_gbs_static", outCanvas_gbs_s, "_gbs");
|
||||
|
||||
ff(outCtx_gbs_a, outCanvas, null, 3, 0, 0)
|
||||
ff(outCtx_gbs_a, outCanvas, FLIP, 3, 0, -2)
|
||||
|
||||
ff(outCtx_gbs_a, outCanvas, null, 4, 0, 3)
|
||||
ff(outCtx_gbs_a, outCanvas, FLIP, 4, 0, -3)
|
||||
|
||||
ff(outCtx_gbs_a, outCanvas, FLIP, 2, 0, -5)
|
||||
ff(outCtx_gbs_a, outCanvas, FLIP, 5, 0, -6)
|
||||
|
||||
GBS_recolor(outCtx_gbs_a, 96);
|
||||
updateExportLink("export_gbs_animated", outCanvas_gbs_a, "_gbs_anim");
|
||||
}
|
||||
|
||||
function parseColorStr(str){
|
||||
return [
|
||||
parseInt(str.substr(1, 2), 16),
|
||||
parseInt(str.substr(3, 2), 16),
|
||||
parseInt(str.substr(5, 2), 16),
|
||||
255
|
||||
];
|
||||
}
|
||||
|
||||
function getColors()
|
||||
{
|
||||
function C(n){
|
||||
return [
|
||||
parseInt(COLORS[gColor][n].substr(1, 2), 16),
|
||||
parseInt(COLORS[gColor][n].substr(3, 2), 16),
|
||||
parseInt(COLORS[gColor][n].substr(5, 2), 16)
|
||||
];
|
||||
}
|
||||
var mode = gColorMode.split('').map(function(n){ return parseInt(n) });
|
||||
var dark = C(mode[0]);
|
||||
var mid = C(mode[1]);
|
||||
var light = C(mode[2]);
|
||||
|
||||
var bg = C(3);
|
||||
|
||||
return { dark:dark, mid:mid, light:light, bg:bg };
|
||||
}
|
||||
|
||||
function recolor(data, getColors)
|
||||
{
|
||||
var tmp = getColors();
|
||||
var put1 = function(i, r, g, b, a) {
|
||||
data[i+0] = r; data[i+1] = g; data[i+2] = b; data[i+3] = a;
|
||||
}
|
||||
for (var i=0; i<data.length; i+=4) {
|
||||
var r = data[i];
|
||||
if(r<50){
|
||||
put1(i, tmp.dark[0], tmp.dark[1], tmp.dark[2], 255);
|
||||
} else if(r<180){
|
||||
put1(i, tmp.mid[0], tmp.mid[1], tmp.mid[2], 255);
|
||||
} else if(r<245){
|
||||
put1(i, tmp.light[0], tmp.light[1], tmp.light[2], 255);
|
||||
} else {
|
||||
put1(i, tmp.bg[0], tmp.bg[1], tmp.bg[2], tmp.bg[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateExportLink(id, canvas, suffix)
|
||||
{
|
||||
// it's always a small file so this should be good enough:
|
||||
var str = Object.keys(gParts).sort().map(function(k){
|
||||
return ("00"+gParts[k]).slice(-2);
|
||||
}).join('')
|
||||
var exportlink = document.getElementById(id)
|
||||
exportlink.href = canvas.toDataURL("image/png");
|
||||
exportlink.download = str + suffix + '.png';
|
||||
}
|
||||
|
||||
function updateOutCanvas() {
|
||||
outCtx.clearRect(0, 0, outCanvas.width, outCanvas.height);
|
||||
|
||||
outCtx.drawImage(gTextures['base'], 0, 0); // base
|
||||
|
||||
drawPart("hair");
|
||||
drawPart("torso");
|
||||
drawPart("ears");
|
||||
drawPart("mouth");
|
||||
drawPart("eyes");
|
||||
drawPart("hands", 0);
|
||||
|
||||
// back of the hair
|
||||
drawPart("hair", null, 4);
|
||||
drawPart("hair", null, 1);
|
||||
|
||||
updateGBS()
|
||||
|
||||
|
||||
var imageData = outCtx.getImageData(0, 0, outCanvas.width, outCanvas.height);
|
||||
var data = imageData.data
|
||||
|
||||
recolor(data, getColors);
|
||||
|
||||
outCtx.putImageData(imageData,0,0);
|
||||
|
||||
updateExportLink("exportlink", outCanvas, "_" + gColor + gColorMode)
|
||||
// // it's always a small file so this should be good enough:
|
||||
// var str = Object.keys(gParts).sort().map(function(k){
|
||||
// return ("00"+gParts[k]).slice(-2);
|
||||
// }).join('') + "_" + gColor + gColorMode;
|
||||
// var exportlink = document.getElementById("exportlink")
|
||||
// exportlink.href = outCanvas.toDataURL("image/png");
|
||||
// exportlink.download = str + '.png';
|
||||
// document.getElementById('serialized_input').value = s;
|
||||
}
|
||||
|
||||
function prefixInputWithASpan(input, text){
|
||||
var span = document.createElement("span");
|
||||
span.innerText = text;
|
||||
input.parentElement.prepend(span);
|
||||
}
|
||||
|
||||
function setupInput(key){
|
||||
var input = document.getElementById(key + "Input");
|
||||
prefixInputWithASpan(input, key)
|
||||
input.setAttribute('min', 0);
|
||||
input.setAttribute('max', PARTS_MAX[key]);
|
||||
input.value = parseInt(Math.random() * (PARTS_MAX[key] + 1));
|
||||
var inputUpdate = function(e){
|
||||
gParts[key] = parseInt(e.target.value);
|
||||
console.log("INPUT UPDATE", e.target.value, gParts);
|
||||
updateOutCanvas();
|
||||
}
|
||||
inputUpdate({ target: input });
|
||||
input.onchange = inputUpdate;
|
||||
input.oninput = inputUpdate;
|
||||
};
|
||||
|
||||
function setupColorInput() {
|
||||
var key = 'color';
|
||||
var input = document.getElementById(key + "Input");
|
||||
prefixInputWithASpan(input, 'colors')
|
||||
|
||||
input.setAttribute('min', 0);
|
||||
input.setAttribute('max', COLORS.length - 1);
|
||||
PARTS_MAX['color'] = COLORS.length;
|
||||
input.value = 0;
|
||||
var inputUpdate = function(e){
|
||||
gColor = parseInt(e.target.value);
|
||||
console.log("COLOR UPDATE", e.target.value, gColor);
|
||||
document.getElementById('colorinfo').innerText = COLORS[gColor][4];
|
||||
updateOutCanvas();
|
||||
}
|
||||
inputUpdate({ target: input });
|
||||
input.onchange = inputUpdate;
|
||||
input.oninput = inputUpdate;
|
||||
}
|
||||
|
||||
function setupColorMode() {
|
||||
var btn = document.getElementById("colormode");
|
||||
|
||||
btn.onclick = function() {
|
||||
if(gColorMode == '012'){ gColorMode = '023' }
|
||||
else if(gColorMode == '023'){ gColorMode = '013' }
|
||||
else if(gColorMode == '013'){ gColorMode = '123' }
|
||||
else { gColorMode = '012' }
|
||||
|
||||
btn.innerText = gColorMode;
|
||||
|
||||
updateOutCanvas();
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
|
||||
terms.json: terms.yaml
|
||||
python3 update_terms_yaml_to_json.py $< $@
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 308 B |
@ -0,0 +1,46 @@
|
||||
.creature canvas {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.creature {
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
margin: 10em;
|
||||
}
|
||||
div.centerbottom {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
}
|
||||
div.caption {
|
||||
/* border: 1px solid black; */
|
||||
position: absolute;
|
||||
left: -120px;
|
||||
width: 240px;
|
||||
}
|
||||
div.caption .corner {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
left: 49%;
|
||||
background-image: url("corner.png");
|
||||
}
|
||||
div.caption div.captiontext {
|
||||
/* height: 4em; */
|
||||
width: 100%;
|
||||
border: 1px solid black;
|
||||
/* top | right | bottom | left */
|
||||
padding: 0 0.3em 0.3em 0.3em;
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
var a = function(n) {
|
||||
return n
|
||||
.split(',')
|
||||
.map(function(k){ return { x: parseInt(k), f: !!k.match('f')} });
|
||||
}
|
||||
var ANIMS = {
|
||||
stand: a("0"),
|
||||
rotate: a("0,2f,1,2"),
|
||||
run_front: a("0,3,0f,3f"),
|
||||
run_back: a("1,4,1f,4f"),
|
||||
run_left: a("2,5"),
|
||||
run_right: a("2f,5f"),
|
||||
}
|
||||
|
||||
class Creature {
|
||||
constructor(img) {
|
||||
this.img = img;
|
||||
if (img.complete) {
|
||||
this.init();
|
||||
} else {
|
||||
img.addEventListener("load", this.init.bind(this));
|
||||
}
|
||||
}
|
||||
init () {
|
||||
this.div = document.createElement("div");
|
||||
this.div.classList.add("creature");
|
||||
this.canvas = document.createElement("canvas");
|
||||
this.img.parentNode.replaceChild(this.div, this.img);
|
||||
this.div.appendChild(this.canvas);
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
this.canvas.width = 16;
|
||||
this.canvas.height = 16;
|
||||
this.ctx.drawImage(this.img, 0, 0);
|
||||
// this.canvas.title = this.img.title;
|
||||
this.centerbottom = document.createElement("div");
|
||||
this.centerbottom.classList.add("centerbottom");
|
||||
this.caption_div = document.createElement("div");
|
||||
this.caption_corner = document.createElement("div");
|
||||
this.caption = document.createElement("div");
|
||||
this.caption_div.classList.add("caption");
|
||||
this.caption_corner.classList.add("corner");
|
||||
this.caption.classList.add("captiontext");
|
||||
this.caption_div.appendChild(this.caption_corner);
|
||||
this.caption_div.appendChild(this.caption);
|
||||
this.div.appendChild(this.centerbottom);
|
||||
this.centerbottom.appendChild(this.caption_div);
|
||||
this.caption.textContent = this.img.title;
|
||||
this.currentAnimName = "stand";
|
||||
this.canvas.addEventListener("click", this.click.bind(this));
|
||||
}
|
||||
animate(){
|
||||
this.ctx.clearRect(0, 0, 16, 16);
|
||||
var t = Date.now ? Date.now() : +(new Date());
|
||||
|
||||
var nt = parseInt(t / 200)
|
||||
var anim = ANIMS[this.currentAnimName];
|
||||
var len = anim.length;
|
||||
|
||||
var findex = nt % len;
|
||||
var frame = anim[findex];
|
||||
const ctx = this.ctx;
|
||||
|
||||
ctx.save();
|
||||
if(frame.f){
|
||||
this.ctx.translate(16, 0);
|
||||
this.ctx.scale(-1, 1);
|
||||
}
|
||||
ctx.drawImage(this.img, frame.x * 16, 0, 16, 16, 0, 0, 16, 16);
|
||||
ctx.restore();
|
||||
}
|
||||
click () {
|
||||
console.log("click", this);
|
||||
this.currentAnimName = "run_front";
|
||||
window.setInterval(this.animate.bind(this), 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.querySelectorAll("img.creature").forEach ( img => {
|
||||
new Creature(img);
|
||||
})
|
@ -0,0 +1,83 @@
|
||||
body, html { background: #fff; text-align: center; }
|
||||
* { box-sizing: border-box; font-family: monospace; font-size: 14px; }
|
||||
h1 { font-size: 28px; margin: 0 0 10px 0; padding: 0; }
|
||||
#root {
|
||||
width: 460px;
|
||||
/* white-space: nowrap; */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
canvas {
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
border: 1px solid black;
|
||||
}
|
||||
#c { width: 144px; height: 144px; padding: 8px; border: none; }
|
||||
|
||||
#outc,
|
||||
#outc_gbs_s,
|
||||
#outc_gbs_a {
|
||||
height: 64px;
|
||||
padding: 8px;
|
||||
display: none;
|
||||
}
|
||||
label { display: block; }
|
||||
label > input { width: 240px; }
|
||||
label > span { display: inline-block; vertical-align: middle; width: 55px; }
|
||||
input[type=range]{ vertical-align: middle; }
|
||||
|
||||
#inputs { display: inline-block; vertical-align: top; text-align: left; margin-top: 1em;}
|
||||
|
||||
.btn, button { background: #fff; text-align: center; min-width: 144px; display: inline-block; padding: 16px 32px; border: 1px solid black; color: black; text-decoration: none; font-size: 1em; margin: 0 0 10px 0; }
|
||||
.btn:hover, button:hover { background: #eee }
|
||||
.btn:active, button:active{ background: #ccc }
|
||||
|
||||
.sm {
|
||||
min-width: 40px;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
|
||||
.rootloading { display: none }
|
||||
|
||||
div.colormode { max-width: 240px; white-space: nowrap }
|
||||
|
||||
#caption {
|
||||
font-family: monospace;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
div.caption {
|
||||
/* border: 3px solid black; */
|
||||
position: relative;
|
||||
width: fit-content;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
div.caption .corner {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
position: absolute;
|
||||
top: -9px;
|
||||
left: 49%;
|
||||
background-image: url("corner.png");
|
||||
}
|
||||
div.caption textarea {
|
||||
width: 320px;
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
#colofon {
|
||||
text-align: left;
|
||||
}
|
||||
#info, #info p {
|
||||
font-family: serif;
|
||||
}
|
||||
#info {
|
||||
padding: 0 1em 0 1em;
|
||||
border: 1px solid black;
|
||||
text-align: left;
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/* https://codepen.io/josfabre/pen/EBMWwW */
|
||||
|
||||
body {
|
||||
background-color: #CCC;
|
||||
padding: 60px;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 20px;
|
||||
text-align: center;
|
||||
font-family: "Press Start 2P", cursive;
|
||||
font-size: 16px;
|
||||
line-height: 1.3em;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
padding: 4px;
|
||||
box-shadow: 0 -4px #fff, 0 -8px #000, 4px 0 #fff, 4px -4px #000, 8px 0 #000, 0 4px #fff, 0 8px #000, -4px 0 #fff, -4px 4px #000, -8px 0 #000, -4px -4px #000, 4px 4px #000;
|
||||
box-sizing: border-box;
|
||||
width: 200px;
|
||||
}
|
||||
.bubble::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.bubble.shadow {
|
||||
box-shadow: 0 -4px #fff, 0 -8px #000, 4px 0 #fff, 4px -4px #000, 8px 0 #000, 0 4px #fff, 0 8px #000, -4px 0 #fff, -4px 4px #000, -8px 0 #000, -4px -4px #000, 4px 4px #000, 4px 12px rgba(0, 0, 0, 0.1), 12px 4px rgba(0, 0, 0, 0.1), 8px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.bubble.mini {
|
||||
width: 110px;
|
||||
font-size: 16px;
|
||||
padding: 4px;
|
||||
font-family: monospace;
|
||||
}
|
||||
.bubble.medium {
|
||||
width: 350px;
|
||||
}
|
||||
.bubble.large {
|
||||
width: 560px;
|
||||
font-size: 24px;
|
||||
text-align: left;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.bubble.grow {
|
||||
width: initial;
|
||||
}
|
||||
.bubble.top::after {
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
top: -8px;
|
||||
left: 32px;
|
||||
box-shadow: 0 -4px #000, 0 -8px #000, 0 -12px #000, 0 -16px #000, -4px -12px #000, -8px -8px #000, -12px -4px #000, -4px -4px #fff, -8px -4px #fff, -4px -8px #fff, -4px 0 #fff, -8px 0 #fff, -12px 0 #fff;
|
||||
}
|
||||
.bubble.right::after {
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
top: 84px;
|
||||
right: -8px;
|
||||
background: white;
|
||||
box-shadow: 4px -4px #fff, 4px 0 #fff, 8px 0 #fff, 0 -8px #fff, 4px 4px #000, 8px 4px #000, 12px 4px #000, 16px 4px #000, 12px 0 #000, 8px -4px #000, 4px -8px #000, 0 -4px #fff;
|
||||
}
|
||||
.bubble.bottom::after {
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
bottom: -8px;
|
||||
left: 32px;
|
||||
box-shadow: 0 4px #000, 0 8px #000, 0 12px #000, 0 16px #000, -4px 12px #000, -8px 8px #000, -12px 4px #000, -4px 4px #fff, -8px 4px #fff, -4px 8px #fff, -4px 0 #fff, -8px 0 #fff, -12px 0 #fff;
|
||||
}
|
||||
.bubble.left::after {
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
top: 20px;
|
||||
left: -8px;
|
||||
background: white;
|
||||
box-shadow: -4px -4px #fff, -4px 0 #fff, -8px 0 #fff, 0 -8px #fff, -4px 4px #000, -8px 4px #000, -12px 4px #000, -16px 4px #000, -12px 0 #000, -8px -4px #000, -4px -8px #000, 0 -4px #fff;
|
||||
}
|
||||
|
||||
.bubble textarea {
|
||||
width: 100%;
|
||||
height: 6em;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.bubble textarea:focus {
|
||||
outline: none !important;
|
||||
border: none;
|
||||
/* box-shadow: 0 0 10px #719ECE; */
|
||||
}
|
||||
|
||||
|
||||
canvas.creature {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
border: none;
|
||||
}
|
@ -0,0 +1,332 @@
|
||||
{
|
||||
"intro": [
|
||||
"I'm a(n)",
|
||||
"I am a(n)",
|
||||
"I aim to be a(n)",
|
||||
"Some call me a(n)",
|
||||
"I'm known to be a(n)",
|
||||
"Someday I will be a(n)"
|
||||
],
|
||||
"action": [
|
||||
"researching",
|
||||
"studying",
|
||||
"scanning",
|
||||
"inflitrating",
|
||||
"uploading",
|
||||
"seeding",
|
||||
"screening",
|
||||
"spamming",
|
||||
"tweeting",
|
||||
"tooting",
|
||||
"singing",
|
||||
"feeling",
|
||||
"listening to",
|
||||
"playing",
|
||||
"reading",
|
||||
"disrupting",
|
||||
"acting as",
|
||||
"dancing",
|
||||
"seeing",
|
||||
"cooking",
|
||||
"preaching",
|
||||
"translating",
|
||||
"yelling",
|
||||
"screaming",
|
||||
"running",
|
||||
"whistleblowing",
|
||||
"leaking",
|
||||
"painting",
|
||||
"writing",
|
||||
"laughing at",
|
||||
"dictating",
|
||||
"designing",
|
||||
"destroying",
|
||||
"showing",
|
||||
"debating",
|
||||
"creating",
|
||||
"performing",
|
||||
"building",
|
||||
"hiding",
|
||||
"surveilling",
|
||||
"faking",
|
||||
"banning",
|
||||
"watching",
|
||||
"deciding",
|
||||
"dealing",
|
||||
"exchanging",
|
||||
"mediating",
|
||||
"fighting",
|
||||
"vandalizing",
|
||||
"parodying",
|
||||
"questioning",
|
||||
"criticizing",
|
||||
"provoking",
|
||||
"obscuring",
|
||||
"shouting on",
|
||||
"controlling",
|
||||
"demanding",
|
||||
"delivering",
|
||||
"disclosing",
|
||||
"developing",
|
||||
"divulging",
|
||||
"lying about",
|
||||
"bragging about",
|
||||
"echoing",
|
||||
"portraying",
|
||||
"helping",
|
||||
"hiding",
|
||||
"interrupting",
|
||||
"conspiring",
|
||||
"sending",
|
||||
"repairing",
|
||||
"disagreeing"
|
||||
],
|
||||
"actor": [
|
||||
"hipster",
|
||||
"scener",
|
||||
"seeder",
|
||||
"leecher",
|
||||
"pirate",
|
||||
"librarian",
|
||||
"virus",
|
||||
"AI",
|
||||
"wizard",
|
||||
"quant",
|
||||
"CEO",
|
||||
"shareholder",
|
||||
"user",
|
||||
"stenographer",
|
||||
"maker",
|
||||
"artist",
|
||||
"professional",
|
||||
"hobbyist",
|
||||
"amateur",
|
||||
"teacher",
|
||||
"student",
|
||||
"doctor",
|
||||
"patient",
|
||||
"public",
|
||||
"criminal",
|
||||
"cook",
|
||||
"editor",
|
||||
"programmer",
|
||||
"preacher",
|
||||
"livecoder",
|
||||
"individual",
|
||||
"visitor",
|
||||
"hacker",
|
||||
"reader",
|
||||
"consumer",
|
||||
"mediator",
|
||||
"actor",
|
||||
"builder",
|
||||
"child",
|
||||
"adult",
|
||||
"architect",
|
||||
"tourist",
|
||||
"person",
|
||||
"parent",
|
||||
"photographer",
|
||||
"musician",
|
||||
"designer",
|
||||
"chatbot",
|
||||
"regulator",
|
||||
"dancer",
|
||||
"developer",
|
||||
"author",
|
||||
"robot",
|
||||
"dog",
|
||||
"cat",
|
||||
"judge",
|
||||
"celebrity",
|
||||
"computer",
|
||||
"politician",
|
||||
"president",
|
||||
"manager",
|
||||
"entrepreneur",
|
||||
"whistleblower",
|
||||
"infiltrator",
|
||||
"book binder",
|
||||
"collective"
|
||||
],
|
||||
"media": [
|
||||
"image boards",
|
||||
"forums",
|
||||
"warez",
|
||||
"screens",
|
||||
"galleries",
|
||||
"screensavers",
|
||||
"viruses",
|
||||
"frequencies",
|
||||
"files",
|
||||
"operating systems",
|
||||
"databases",
|
||||
"privacy",
|
||||
"posters",
|
||||
"cybernetics",
|
||||
"floppy disks",
|
||||
"CD-ROMs",
|
||||
"LaserDiscs",
|
||||
"apps",
|
||||
"spam",
|
||||
"startups",
|
||||
"manuscripts",
|
||||
"carpets",
|
||||
"markets",
|
||||
"architectures",
|
||||
"feels",
|
||||
"books",
|
||||
"games",
|
||||
"radio",
|
||||
"music",
|
||||
"graffitis",
|
||||
"blogs",
|
||||
"theatre",
|
||||
"woodblocks",
|
||||
"dances",
|
||||
"recycling",
|
||||
"emails",
|
||||
"food",
|
||||
"migration",
|
||||
"magazines",
|
||||
"maps",
|
||||
"comics",
|
||||
"finance",
|
||||
"teaching",
|
||||
"memes",
|
||||
"futures",
|
||||
"traditions",
|
||||
"corruption",
|
||||
"regulation",
|
||||
"porn",
|
||||
"webpages",
|
||||
"vandalism",
|
||||
"samizdat",
|
||||
"ethics",
|
||||
"billboards",
|
||||
"advertising",
|
||||
"manifestos",
|
||||
"leaflets",
|
||||
"browsers",
|
||||
"wikis",
|
||||
"canvases",
|
||||
"tapes",
|
||||
"vinyls",
|
||||
"records",
|
||||
"synthesizers",
|
||||
"feeds",
|
||||
"newspapers",
|
||||
"HTML pages",
|
||||
"codex",
|
||||
"software",
|
||||
"codes of conduct",
|
||||
"epubs",
|
||||
"PDFs",
|
||||
"NFTs",
|
||||
"stories",
|
||||
"dictionaries",
|
||||
"libraries",
|
||||
"bugs",
|
||||
"disagreements"
|
||||
],
|
||||
"prefix": [
|
||||
"proto",
|
||||
"xeno",
|
||||
"cyber",
|
||||
"retro",
|
||||
"pre",
|
||||
"ante",
|
||||
"proto",
|
||||
"post",
|
||||
"avant",
|
||||
"neo",
|
||||
"anti",
|
||||
"co",
|
||||
"epi",
|
||||
"ex",
|
||||
"extra",
|
||||
"hyper",
|
||||
"infra",
|
||||
"inter",
|
||||
"macro",
|
||||
"micro",
|
||||
"mid",
|
||||
"mono",
|
||||
"non",
|
||||
"multi",
|
||||
"omni",
|
||||
"semi",
|
||||
"sub",
|
||||
"super",
|
||||
"trans",
|
||||
"cross",
|
||||
"uni",
|
||||
"minor"
|
||||
],
|
||||
"sort": [
|
||||
"bootleg",
|
||||
"capitalist",
|
||||
"progressive",
|
||||
"organic",
|
||||
"industrial",
|
||||
"homemade",
|
||||
"craft",
|
||||
"AI",
|
||||
"encrypted",
|
||||
"inclusive",
|
||||
"fair",
|
||||
"transparent",
|
||||
"command line",
|
||||
"granular",
|
||||
"crypto",
|
||||
"centralised",
|
||||
"free",
|
||||
"libre",
|
||||
"open",
|
||||
"proprietary",
|
||||
"DIY",
|
||||
"DIWO",
|
||||
"homebrew",
|
||||
"decentralised",
|
||||
"closed source",
|
||||
"binary",
|
||||
"plaintext",
|
||||
"federated",
|
||||
"distributed",
|
||||
"online",
|
||||
"offline",
|
||||
"raw",
|
||||
"compressed",
|
||||
"deep",
|
||||
"dark",
|
||||
"common",
|
||||
"shared",
|
||||
"liberal",
|
||||
"anarcho-capitalist",
|
||||
"anarcho-communist",
|
||||
"anarcho-syndicalist",
|
||||
"authoritarian",
|
||||
"capitalist",
|
||||
"communist",
|
||||
"marxist",
|
||||
"apolitical",
|
||||
"syndicated",
|
||||
"digital",
|
||||
"analog",
|
||||
"bottom-up",
|
||||
"top-down",
|
||||
"horizontal",
|
||||
"vertical",
|
||||
"agonistic",
|
||||
"version-controlled",
|
||||
"feminist",
|
||||
"decolonial",
|
||||
"contradictory",
|
||||
"occasional",
|
||||
"layered",
|
||||
"entangled",
|
||||
"collective",
|
||||
"complex",
|
||||
"artificial"
|
||||
]
|
||||
}
|
@ -0,0 +1,324 @@
|
||||
intro:
|
||||
- I'm a(n)
|
||||
- I am a(n)
|
||||
- I aim to be a(n)
|
||||
- Some call me a(n)
|
||||
- I'm known to be a(n)
|
||||
- Someday I will be a(n)
|
||||
action:
|
||||
- researching
|
||||
- studying
|
||||
- scanning
|
||||
- inflitrating
|
||||
- uploading
|
||||
- seeding
|
||||
- screening
|
||||
- spamming
|
||||
- tweeting
|
||||
- tooting
|
||||
- singing
|
||||
- feeling
|
||||
- listening to
|
||||
- playing
|
||||
- reading
|
||||
- disrupting
|
||||
- acting as
|
||||
- dancing
|
||||
- seeing
|
||||
- cooking
|
||||
- preaching
|
||||
- translating
|
||||
- yelling
|
||||
- screaming
|
||||
- running
|
||||
- whistleblowing
|
||||
- leaking
|
||||
- painting
|
||||
- writing
|
||||
- laughing at
|
||||
- dictating
|
||||
- designing
|
||||
- destroying
|
||||
- showing
|
||||
- debating
|
||||
- creating
|
||||
- performing
|
||||
- building
|
||||
- hiding
|
||||
- surveilling
|
||||
- faking
|
||||
- banning
|
||||
- watching
|
||||
- deciding
|
||||
- dealing
|
||||
- exchanging
|
||||
- mediating
|
||||
- fighting
|
||||
- vandalizing
|
||||
- parodying
|
||||
- questioning
|
||||
- criticizing
|
||||
- provoking
|
||||
- obscuring
|
||||
- shouting on
|
||||
- controlling
|
||||
- demanding
|
||||
- delivering
|
||||
- disclosing
|
||||
- developing
|
||||
- divulging
|
||||
- lying about
|
||||
- bragging about
|
||||
- echoing
|
||||
- portraying
|
||||
- helping
|
||||
- hiding
|
||||
- interrupting
|
||||
- conspiring
|
||||
- sending
|
||||
- repairing
|
||||
- disagreeing
|
||||
actor:
|
||||
- hipster
|
||||
- scener
|
||||
- seeder
|
||||
- leecher
|
||||
- pirate
|
||||
- librarian
|
||||
- virus
|
||||
- AI
|
||||
- wizard
|
||||
- quant
|
||||
- CEO
|
||||
- shareholder
|
||||
- user
|
||||
- stenographer
|
||||
- maker
|
||||
- artist
|
||||
- professional
|
||||
- hobbyist
|
||||
- amateur
|
||||
- teacher
|
||||
- student
|
||||
- doctor
|
||||
- patient
|
||||
- public
|
||||
- criminal
|
||||
- cook
|
||||
- editor
|
||||
- programmer
|
||||
- preacher
|
||||
- livecoder
|
||||
- individual
|
||||
- visitor
|
||||
- hacker
|
||||
- reader
|
||||
- consumer
|
||||
- mediator
|
||||
- actor
|
||||
- builder
|
||||
- child
|
||||
- adult
|
||||
- architect
|
||||
- tourist
|
||||
- person
|
||||
- parent
|
||||
- photographer
|
||||
- musician
|
||||
- designer
|
||||
- chatbot
|
||||
- regulator
|
||||
- dancer
|
||||
- developer
|
||||
- author
|
||||
- robot
|
||||
- dog
|
||||
- cat
|
||||
- judge
|
||||
- celebrity
|
||||
- computer
|
||||
- politician
|
||||
- president
|
||||
- manager
|
||||
- entrepreneur
|
||||
- whistleblower
|
||||
- infiltrator
|
||||
- book binder
|
||||
- collective
|
||||
media:
|
||||
- image boards
|
||||
- forums
|
||||
- warez
|
||||
- screens
|
||||
- galleries
|
||||
- screensavers
|
||||
- viruses
|
||||
- frequencies
|
||||
- files
|
||||
- operating systems
|
||||
- databases
|
||||
- privacy
|
||||
- posters
|
||||
- cybernetics
|
||||
- floppy disks
|
||||
- CD-ROMs
|
||||
- LaserDiscs
|
||||
- apps
|
||||
- spam
|
||||
- startups
|
||||
- manuscripts
|
||||
- carpets
|
||||
- markets
|
||||
- architectures
|
||||
- feels
|
||||
- books
|
||||
- games
|
||||
- radio
|
||||
- music
|
||||
- graffitis
|
||||
- blogs
|
||||
- theatre
|
||||
- woodblocks
|
||||
- dances
|
||||
- recycling
|
||||
- emails
|
||||
- food
|
||||
- migration
|
||||
- magazines
|
||||
- maps
|
||||
- comics
|
||||
- finance
|
||||
- teaching
|
||||
- memes
|
||||
- futures
|
||||
- traditions
|
||||
- corruption
|
||||
- regulation
|
||||
- porn
|
||||
- webpages
|
||||
- vandalism
|
||||
- samizdat
|
||||
- ethics
|
||||
- billboards
|
||||
- advertising
|
||||
- manifestos
|
||||
- leaflets
|
||||
- browsers
|
||||
- wikis
|
||||
- canvases
|
||||
- tapes
|
||||
- vinyls
|
||||
- records
|
||||
- synthesizers
|
||||
- feeds
|
||||
- newspapers
|
||||
- HTML pages
|
||||
- codex
|
||||
- software
|
||||
- codes of conduct
|
||||
- epubs
|
||||
- PDFs
|
||||
- NFTs
|
||||
- stories
|
||||
- dictionaries
|
||||
- libraries
|
||||
- bugs
|
||||
- disagreements
|
||||
prefix:
|
||||
- proto
|
||||
- xeno
|
||||
- cyber
|
||||
- retro
|
||||
- pre
|
||||
- ante
|
||||
- proto
|
||||
- post
|
||||
- avant
|
||||
- neo
|
||||
- anti
|
||||
- co
|
||||
- epi
|
||||
- ex
|
||||
- extra
|
||||
- hyper
|
||||
- infra
|
||||
- inter
|
||||
- macro
|
||||
- micro
|
||||
- mid
|
||||
- mono
|
||||
- non
|
||||
- multi
|
||||
- omni
|
||||
- semi
|
||||
- sub
|
||||
- super
|
||||
- trans
|
||||
- cross
|
||||
- uni
|
||||
- minor
|
||||
sort:
|
||||
- bootleg
|
||||
- capitalist
|
||||
- progressive
|
||||
- organic
|
||||
- industrial
|
||||
- homemade
|
||||
- craft
|
||||
- AI
|
||||
- encrypted
|
||||
- inclusive
|
||||
- fair
|
||||
- transparent
|
||||
- command line
|
||||
- granular
|
||||
- crypto
|
||||
- centralised
|
||||
- free
|
||||
- libre
|
||||
- open
|
||||
- proprietary
|
||||
- DIY
|
||||
- DIWO
|
||||
- homebrew
|
||||
- decentralised
|
||||
- closed source
|
||||
- binary
|
||||
- plaintext
|
||||
- federated
|
||||
- distributed
|
||||
- online
|
||||
- offline
|
||||
- raw
|
||||
- compressed
|
||||
- deep
|
||||
- dark
|
||||
- common
|
||||
- shared
|
||||
- liberal
|
||||
- anarcho-capitalist
|
||||
- anarcho-communist
|
||||
- anarcho-syndicalist
|
||||
- authoritarian
|
||||
- capitalist
|
||||
- communist
|
||||
- marxist
|
||||
- apolitical
|
||||
- syndicated
|
||||
- digital
|
||||
- analog
|
||||
- bottom-up
|
||||
- top-down
|
||||
- horizontal
|
||||
- vertical
|
||||
- agonistic
|
||||
- version-controlled
|
||||
- feminist
|
||||
- decolonial
|
||||
- contradictory
|
||||
- occasional
|
||||
- layered
|
||||
- entangled
|
||||
- collective
|
||||
- complex
|
||||
- artificial
|
@ -0,0 +1,16 @@
|
||||
import click
|
||||
import yaml
|
||||
import json
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('input', type=click.File('r'))
|
||||
@click.argument('output', type=click.File('w'))
|
||||
@click.argument('indent', type=int, default=2)
|
||||
def yaml_to_json(input, output, indent):
|
||||
"""Convert a YAML input to JSON output"""
|
||||
d = yaml.safe_load(input)
|
||||
json.dump(d, output, indent=indent)
|
||||
|
||||
if __name__ == '__main__':
|
||||
yaml_to_json()
|
@ -0,0 +1,9 @@
|
||||
canvas {
|
||||
image-rendering: optimizeSpeed;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
border: 1px solid black;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
var stage = new createjs.Stage('canvas');
|
||||
|
||||
// var shape = new createjs.Shape();
|
||||
// shape.graphics.beginFill('red').drawRect(0, 0, 120, 120);
|
||||
// stage.addChild(shape);
|
||||
// stage.update();
|
||||
|
||||
var ss = new createjs.SpriteSheet({
|
||||
frames: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
regX: 0,
|
||||
regY: 0,
|
||||
spacing: 0,
|
||||
margin: 0,
|
||||
count: 6
|
||||
},
|
||||
animations: {stand: 0, run: [0, 3]},
|
||||
images: [document.querySelector("#creature-src")]
|
||||
});
|
||||
|
||||
var sprite = new createjs.Sprite(ss, "stand");
|
||||
sprite.scaleY = sprite.scaleX = 4;
|
||||
stage.addChild(sprite);
|
||||
|
||||
sprite.on("click", function() { sprite.gotoAndPlay("jump"); });
|
||||
|
||||
createjs.Ticker.on("tick", stage);
|
@ -0,0 +1,123 @@
|
||||
// function prefixInputWithASpan(input, text){
|
||||
// var span = document.createElement("span");
|
||||
// span.innerText = text;
|
||||
// input.parentElement.prepend(span);
|
||||
// }
|
||||
|
||||
let terms;
|
||||
let cParts = {};
|
||||
|
||||
function setupTextInput(key){
|
||||
var input = document.getElementById(key + "Input");
|
||||
prefixInputWithASpan(input, key)
|
||||
input.setAttribute('min', 0);
|
||||
input.setAttribute('max', terms[key].length - 1);
|
||||
input.value = parseInt(Math.random() * (terms[key].length + 1));
|
||||
var inputUpdate = function(e){
|
||||
// gParts[key] = parseInt(e.target.value);
|
||||
// console.log("INPUT UPDATE", e.target.value, gParts);
|
||||
// updateOutCanvas();
|
||||
console.log("INPUT UPDATE", e.target.value);
|
||||
cParts[key] = parseInt(e.target.value);
|
||||
updateCaption();
|
||||
}
|
||||
inputUpdate({ target: input });
|
||||
input.onchange = inputUpdate;
|
||||
input.oninput = inputUpdate;
|
||||
};
|
||||
|
||||
let grammar = ["intro", "actor", "action", "prefix", "sort", "media"];
|
||||
function updateCaption () {
|
||||
let caption = "";
|
||||
for (let gi=grammar.length-1; gi>=0; gi--) {
|
||||
let key = grammar[gi];
|
||||
let term = terms[key][cParts[key]];
|
||||
if (!term) break;
|
||||
console.log(`key: ${key}, term: ${term}`)
|
||||
if (term.match(/a\(n\)/)) {
|
||||
console.log(`doing a(n) replacement on ${term}, for [${caption}]`);
|
||||
if (caption.match(/^[aeiou]/i)) {
|
||||
console.log("VOWEL");
|
||||
term = term.replace(/a\(n\)/, "an");
|
||||
} else {
|
||||
term = term.replace(/a\(n\)/, "a");
|
||||
}
|
||||
}
|
||||
caption = term + (caption?" ":"") + caption;
|
||||
}
|
||||
// grammar.forEach(key => {
|
||||
// caption += (caption ? " " : "") + terms[key][cParts[key]];
|
||||
// })
|
||||
document.querySelector("#caption").innerHTML = caption;
|
||||
}
|
||||
|
||||
async function start () {
|
||||
const src = document.querySelector("a#terms-data-source").href;
|
||||
terms = await (await fetch(src)).json();
|
||||
console.log("terms", terms);
|
||||
setupTextInput("intro");
|
||||
setupTextInput("action");
|
||||
setupTextInput("actor");
|
||||
setupTextInput("media");
|
||||
setupTextInput("prefix");
|
||||
setupTextInput("sort");
|
||||
}
|
||||
|
||||
var randomizebtn = document.getElementById('randomizebtn');
|
||||
randomizebtn.onclick = function() {
|
||||
let inputs = document.getElementById('inputs').querySelectorAll('input.g');
|
||||
|
||||
for(var i=0; i<inputs.length; i++){
|
||||
var input = inputs[i];
|
||||
var key = input.id.replace("Input", "");
|
||||
var max = PARTS_MAX[key];
|
||||
var randval = Math.floor(Math.random() * (max + 1));
|
||||
input.value = randval;
|
||||
gParts[key] = randval;
|
||||
if (key == 'color') {
|
||||
// gColor = randval;
|
||||
input.dispatchEvent(new Event('input', { 'bubbles': true }));
|
||||
}
|
||||
console.log("randomizing", input, randval);
|
||||
}
|
||||
|
||||
updateOutCanvas();
|
||||
|
||||
inputs = document.getElementById('inputs').querySelectorAll('input.c');
|
||||
for(var i=0; i<inputs.length; i++){
|
||||
var input = inputs[i];
|
||||
var key = input.id.replace("Input", "");
|
||||
var max = terms[key].length;
|
||||
var randval = Math.floor(Math.random() * (max + 0));
|
||||
input.value = randval;
|
||||
cParts[key] = randval;
|
||||
}
|
||||
updateCaption();
|
||||
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
function send (canvas, form) {
|
||||
canvas.toBlob(blob => {
|
||||
if (blob) {
|
||||
const formdata = new FormData();
|
||||
const filename = new Date().toISOString() + ".png";
|
||||
formdata.append("image", blob, filename);
|
||||
formdata.append("caption", document.querySelector("#caption").textContent);
|
||||
formdata.append("message", form.message.value);
|
||||
formdata.append("csrfmiddlewaretoken", form.csrfmiddlewaretoken.value);
|
||||
fetch(form.action, { method:"POST", body: formdata })
|
||||
.then(() => {
|
||||
document.querySelector("#inputs").style.display = "none";
|
||||
document.querySelector("#caption").disabled = true;
|
||||
});
|
||||
}
|
||||
}, "image/png");
|
||||
}
|
||||
|
||||
document.querySelector("button#send").addEventListener("click", () => {
|
||||
console.log("SEND");
|
||||
const form = document.querySelector("form");
|
||||
send(outCanvas, form);
|
||||
})
|
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<title>{% block title %}study at XPUB!{% endblock %}</title>
|
||||
<style>{%block style %}{% endblock %}</style>
|
||||
{%block extrahead %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{%block content %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,19 @@
|
||||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang=en>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<title>xpub call 2025</title>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<img src="{{creature.image.url}}">
|
||||
<p>{{creature.caption}}</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,6 @@
|
||||
{% extends "call/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<img src="{{object.image.url}}">
|
||||
<p>{{object.caption}}</p>
|
||||
{% endblock %}
|
@ -0,0 +1,30 @@
|
||||
{% extends "call/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Creatures</h2>
|
||||
<ul>
|
||||
{% for creature in page_obj %}
|
||||
<li><a href="{% url 'walk' creature.id %}">{{ creature.caption }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="step-links">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}">next</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,33 @@
|
||||
{% extends "call/base.html" %}
|
||||
{% load static %}
|
||||
{% block extrahead %}
|
||||
<link rel="stylesheet" href="{%static 'call/guestbook.css' %}">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<marquee><h1>Welcome XPUB Class of 2025-2027</h1></marquee>
|
||||
<div id="content">
|
||||
{% for creature in page_obj %}
|
||||
<img class="creature" src="{{creature.image.url}}" title="{{creature.caption}}">
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="pagination">
|
||||
<span class="step-links">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page=1">« first</a>
|
||||
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span class="current">
|
||||
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||
</span>
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}">next</a>
|
||||
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'call/guestbook.js' %}"></script>
|
||||
{% endblock %}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,57 @@
|
||||
{% load static %}
|
||||
{% block extrahead %}
|
||||
<link rel="stylesheet" href="{% static 'call/statement.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<img src="{{creature.image.url}}" class="creature" style="display: none">
|
||||
|
||||
<canvas class="creature"></canvas>
|
||||
<!-- <p>{{creature.caption}}</p> -->
|
||||
|
||||
|
||||
<!-- <div class="bubble mini top">awesome!</div>
|
||||
<div class="bubble right">I can get you a thumb by three o'clock</div>
|
||||
<div class="bubble medium bottom">I'm not into the whole China thing, man</div>
|
||||
<div class="bubble grow left">This is such a travesty</div>
|
||||
<div class="bubble shadow large bottom">Ik moet nu eerst even een gerestaureerde drol hebben!</div> -->
|
||||
|
||||
<div class="bubble shadow large top"><textarea placeholder="Your messsage" autofocus id="caption"></textarea></div>
|
||||
|
||||
|
||||
<p>The Master Experimental Publishing at the Piet Zwart Institute in Rotterdam (NL) is a two-year master focused on the acts of making things public and creating publics in the age of post-digital networks.</p>
|
||||
<div id="info">
|
||||
<p>Application deadlines:</p>
|
||||
<p>
|
||||
March 4, 2024 (non-EU + EU)<br>
|
||||
May 8, 2024 (EU)<br>
|
||||
</p>
|
||||
<p>Open days:</p>
|
||||
<p>
|
||||
<a href="mailto:pzi.coordinators@hr.nl?subject=XPUB Open Day (online)&body=Hello, I will join the online open day on the February 6th on 10:00 CET or 16:00 CET" target="_blank">February 6, 2024</a> (online)<br>
|
||||
<a href="https://www.pzwart.nl/blog/2023/10/10/open-day/" target="_blank">February 15, 2025</a> (IRL)<br>
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<button id="apply">Apply</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>CSS Speech bubbles from <a href="https://codepen.io/josfabre/pen/EBMWwW">Jos Faber</a>.</p>
|
||||
|
||||
|
||||
<script>
|
||||
// Get canvas context
|
||||
const ctx = document.querySelector("canvas.creature").getContext("2d");
|
||||
|
||||
// Load image
|
||||
const image = new Image();
|
||||
image.onload = () => {
|
||||
// Draw the image into the canvas
|
||||
ctx.drawImage(image, 0, 0, 64);
|
||||
};
|
||||
image.src = document.querySelector("img.creature").src;
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,14 @@
|
||||
{% extends "call/base.html" %}
|
||||
{% load static %}
|
||||
{% block extrahead %}
|
||||
<link rel="stylesheet" href="{% static 'call/walk.css' %}">
|
||||
<script src="{% static 'EaselJS-1.0.0/lib/easeljs.js' %}"></script>
|
||||
<script src="{% static 'TweenJS-1.0.0/lib/tweenjs.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{object}} {{object.image}} {{object.image.url}}
|
||||
<div><img id="creature-src" src="{{object.image.url}}"></div>
|
||||
<canvas id="canvas" width="550" height="250" style="border: 1px dotted gray"></canvas>
|
||||
<script src="{% static 'call/walk.js' %}"></script>
|
||||
{% endblock %}
|
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
@ -0,0 +1,28 @@
|
||||
"""
|
||||
URL configuration for call2025 project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from call import views
|
||||
from .views import Guestbook, CreatureDetail, Statement, Walk
|
||||
|
||||
urlpatterns = [
|
||||
path("guestbook/", Guestbook.as_view(), name="guestbook"),
|
||||
path("creatures/<int:pk>/", CreatureDetail.as_view(), name="creature_detail"),
|
||||
path("creatures/<int:pk>/s/", Statement.as_view(), name="statement"),
|
||||
path("creatures/<int:pk>/w/", Walk.as_view(), name="walk"),
|
||||
path('', views.index)
|
||||
]
|
@ -0,0 +1,41 @@
|
||||
from django.shortcuts import render, HttpResponseRedirect
|
||||
from call.forms import CreatureForm
|
||||
from django.views import generic
|
||||
from .models import Creature
|
||||
from django.urls import reverse
|
||||
|
||||
|
||||
# Create your views here.
|
||||
def index(request):
|
||||
if request.method == "POST":
|
||||
print ("post", request.POST)
|
||||
print ("files", request.FILES)
|
||||
form = CreatureForm(request.POST, request.FILES)
|
||||
# form = CreatureFormNo(request.POST, request.FILES)
|
||||
# formset = AuthorFormSet(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
print ("FORM IS VALID")
|
||||
form.save()
|
||||
return HttpResponseRedirect(reverse("statement", args=(form.instance.id,)))
|
||||
# do something.
|
||||
else:
|
||||
print ("FORM NOT VALID")
|
||||
else:
|
||||
form = CreatureForm()
|
||||
return render(request, "call/index.html", {"form": form})
|
||||
|
||||
class Guestbook(generic.ListView):
|
||||
paginate_by = 20
|
||||
model=Creature
|
||||
template_name = "call/guestbook.html"
|
||||
|
||||
class CreatureDetail(generic.DetailView):
|
||||
model = Creature
|
||||
|
||||
class Statement(generic.DetailView):
|
||||
model = Creature
|
||||
template_name = "call/statement.html"
|
||||
|
||||
class Walk(generic.DetailView):
|
||||
model = Creature
|
||||
template_name = "call/walk.html"
|
@ -0,0 +1,16 @@
|
||||
"""
|
||||
ASGI config for call2025 project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'call2025.settings')
|
||||
|
||||
application = get_asgi_application()
|
@ -0,0 +1,131 @@
|
||||
"""
|
||||
Django settings for call2025 project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.1.5.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-nn7mvrgu6de^%z&6t1usgaji_*59z*v+230tluec-h4fw*n(%i'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'call',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'call2025.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'call2025.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db' / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||
|
||||
# STATIC_URL = 'static/'
|
||||
STATIC_URL = '/call/static/'
|
||||
STATIC_ROOT = "/var/www/wsgi/call2025/static/"
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
MEDIA_ROOT = 'media/'
|
||||
MEDIA_ROOT = "/var/www/wsgi/call2025/media/"
|
||||
MEDIA_URL = 'media/'
|
||||
MEDIA_URL = '/call/media/'
|
@ -0,0 +1,138 @@
|
||||
"""
|
||||
Django settings for call2025 project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 5.1.5.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = 'django-insecure-nn7mvrgu6de^%z&6t1usgaji_*59z*v+230tluec-h4fw*n(%i'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'call',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'call2025.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'call2025.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': BASE_DIR / 'db' / 'db.sqlite3',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||
|
||||
#
|
||||
DEPLOY = False
|
||||
|
||||
if DEPLOY:
|
||||
STATIC_URL = '/call/static/'
|
||||
STATIC_ROOT = "/var/www/wsgi/call2025/static/"
|
||||
else:
|
||||
STATIC_URL = 'static/'
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
if DEPLOY:
|
||||
MEDIA_URL = '/call/media/'
|
||||
MEDIA_ROOT = "/var/www/wsgi/call2025/media/"
|
||||
else:
|
||||
MEDIA_ROOT = 'media/'
|
||||
MEDIA_URL = 'media/'
|
@ -0,0 +1,26 @@
|
||||
"""
|
||||
URL configuration for call2025 project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('', include('call.urls'))
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
@ -0,0 +1,16 @@
|
||||
"""
|
||||
WSGI config for call2025 project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'call2025.settings')
|
||||
|
||||
application = get_wsgi_application()
|
Binary file not shown.
After Width: | Height: | Size: 308 B |
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="2.8504503mm"
|
||||
height="3.0193765mm"
|
||||
viewBox="0 0 2.8504503 3.0193765"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="corner.svg"
|
||||
inkscape:export-filename="corner.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="32.494215"
|
||||
inkscape:cx="7.7552266"
|
||||
inkscape:cy="11.786713"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-47.887113,-41.55363)">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 48.027547,44.560578 v -2.60763 l 2.624924,2.60763"
|
||||
id="path1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Django's command-line utility for administrative tasks."""
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Run administrative tasks."""
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'call2025.settings')
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(sys.argv)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue