Calendar

Generate a plottable calendar

Log in to post a comment.

const month = 10 // min=0, max=11, step=1 (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)
const year = 2021 // min=2020, max=2030, step=1

const first_day = new Date(year, month, 1).getDay()

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);
const rows = 5
const cols = 7
const date_size = 7 // min=3, max=12, step=1
const date_percent = 0.7

// Global code will be evaluated once.
const turtle = new Turtle();
const spacing = Math.min(Math.floor(200 / rows), Math.floor(200 / cols))
const x = (200 - cols * spacing) / 2 - 100
const y = (200 - rows * spacing) / 2 - 100
const seg_len = (date_size * date_percent) / 2

turtle.penup()

function draw_grid() {
    turtle.penup()
    for (let r = 0; r <= rows; r++) {
        turtle.goto(x, y + r * spacing)
        turtle.pendown()
        turtle.goto(x + cols * spacing, y + r * spacing)
        turtle.penup()
    }
    for (let c = 0; c <= cols; c++) {
        turtle.goto(x + c * spacing, y)
        turtle.pendown()
        turtle.goto(x + c * spacing, y + rows * spacing)
        turtle.penup()
    }
}

function draw_corner(r, c) {
    cy = y + spacing * r
    cx = x + spacing * c
    
    turtle.goto(cx, cy)
    turtle.seth(0)
    turtle.forward(date_size)
    turtle.right(90)
    turtle.pendown()
    turtle.forward(date_size)
    turtle.right(90)
    turtle.forward(date_size)
    turtle.penup()
}

function draw_number(x, y, n, seg_len) {
    
    turtle.penup()
    turtle.goto(x, y)
    turtle.seth(0)
    
    switch(n) {
        case 0:
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            break
        case 1:
            turtle.forward(seg_len)
            turtle.pendown()
            turtle.right(90)
            turtle.forward(seg_len * 2)
            break
        case 2:
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            break
        case 3:
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.penup()
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.pendown()
            turtle.forward(seg_len)
            break
        case 4:
            turtle.right(90)
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.penup()
            turtle.backward(seg_len)
            turtle.pendown()
            turtle.backward(seg_len)
            break
        case 5:
            turtle.forward(seg_len)
            turtle.right(180)
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            break
        case 6:
            turtle.forward(seg_len)
            turtle.right(180)
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len * 2)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            turtle.left(90)
            turtle.forward(seg_len)
            break
        case 7:
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            break
        case 8:
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            turtle.penup()
            turtle.backward(seg_len)
            turtle.right(90)
            turtle.pendown()
            turtle.forward(seg_len)
            break
        case 9:
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.pendown()
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len)
            turtle.right(90)
            turtle.forward(seg_len * 2)
            break
            
            
    }
    turtle.penup()
    
}

function draw_date(r, c, d) {
    const h_offset = date_size * (1 - date_percent) / 3
    const v_offset = date_size * (1 - date_percent) / 2
    draw_corner(r, c)
    
    cy = y + spacing * r
    cx = x + spacing * c
    
    if (d > 9) {
        draw_number(cx + h_offset, cy + v_offset, Math.trunc(d / 10), seg_len)
    }
    draw_number(cx + h_offset * 2 + seg_len, cy + v_offset, d % 10, seg_len)
}

function get_month_dates() {
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            day = r * cols + c
            date = new Date(year, month, day - first_day + 1).getDate()
            draw_date(r, c, date)
        }
    }
}

// https://turtletoy.net/turtle/8abd768e03
function drawLetter(let, x, y, size) {
    var points = Letter[let];
    if (typeof points == 'undefined' || points.length < 1) return;
    turtle.penup();
    for (var i = 0; i < points.length - 1; i = i+2) {
        turtle.goto(x+points[i]*size,y-points[i+1]*size);
        if (i == 0) turtle.pendown();
    }
}

function drawWord(word, x, y, size) {
    word = word.toUpperCase();
    for (var i = 0; i < word.length; i++) {
        // repeat the letter shifted to darken/shadow
        [0,0.2].forEach(function(shift) {
            drawLetter(word[i], x+shift, y+shift, size);
        });
        // letter spacing
        if (word[i] == 'I') { x += size-3 } else x += size+1;
    }
}

var Letter = new Array();
Letter['A'] = new Array(0,0,0.5,1,0.75,0.5,0.25,0.5,0.75,0.5,1,0);
Letter['B'] = new Array(0,0,0,1,0.625,1,0.75,0.875,0.75,0.625,0.625,0.5,0,0.5,0.625,0.5,0.75,0.375,0.75,0.125,0.625,0,0,0);
Letter['C'] = new Array(0.75,0.125,0.625,0,0.125,0,0,0.125,0,0.875,0.125,1,0.625,1,0.75,0.875);
Letter['D'] = new Array(0,0,0,1,0.625,1,0.75,0.875,0.75,0.125,0.625,0,0,0);
Letter['E'] = new Array(0.75,0,0,0,0,0.5,0.75,0.5,0,0.5,0,1,0.75,1);
Letter['F'] = new Array(0,0,0,0.5,0.75,0.5,0,0.5,0,1,0.75,1);
Letter['G'] = new Array(0.75,0.5,0.625,0.5,0.75,0.5,0.75,0.125,0.625,0,0.125,0,0,0.125,0,0.875,0.125,1,0.625,1,0.75,0.875);
Letter['H'] = new Array(0,0,0,1,0,0.5,0.75,0.5,0.75,1,0.75,0);
Letter['I'] = new Array(0,0,0.25,0,0.125,0,0.125,1,0,1,0.25,1);
Letter['J'] = new Array(0,0.125,0.125,0,0.375,0,0.5,0.125,0.5,1);
Letter['K'] = new Array(0,0,0,1,0,0.5,0.75,1,0,0.5,0.75,0);
Letter['L'] = new Array(0,0,0,1,0,0,0.75,0);
Letter['M'] = new Array(0,0,0,1,0.5,0,1,1,1,0);
Letter['N'] = new Array(0,0,0,1,0.75,0,0.75,1);
Letter['O'] = new Array(0.75,0.125,0.625,0,0.125,0,0,0.125,0,0.875,0.125,1,0.625,1,0.75,0.875,0.75,0.125);
Letter['P'] = new Array(0,0,0,1,0.625,1,0.75,0.875,0.75,0.625,0.625,0.5,0,0.5);
Letter['Q'] = new Array(0.75,0.125,0.625,0,0.125,0,0,0.125,0,0.875,0.125,1,0.625,1,0.75,0.875,0.75,0.125,0.875,0);
Letter['R'] = new Array(0,0,0,1,0.625,1,0.75,0.875,0.75,0.625,0.625,0.5,0,0.5,0.625,0.5,0.875,0);
Letter['S'] = new Array(0,0.125,0.125,0,0.625,0,0.75,0.125,0.75,0.375,0.675,0.5,0.125,0.5,0,0.625,0,0.875,0.125,1,0.625,1,0.75,0.875);
Letter['T'] = new Array(0,1,0.5,1,0.5,0,0.5,1,1,1);
Letter['U'] = new Array(0,1,0,0.125,0.125,0,0.625,0,0.75,0.125,0.75,1);
Letter['V'] = new Array(0,1,0.375,0,0.75,1);
Letter['W'] = new Array(0,1,0.25,0,0.5,1,0.75,0,1,1);
Letter['X'] = new Array(0,0,0.375,0.5,0,1,0.375,0.5,0.75,1,0.375,0.5,0.75,0);
Letter['Y'] = new Array(0,1,0.375,0.5,0.375,0,0.375,0.5,0.75,1);
Letter['Z'] = new Array(0,1,0.75,1,0,0,0.75,0);
Letter[' '] = new Array();

Months = new Array('JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER')
// The walk function will be called until it returns false.
function walk(i) {
   
    draw_grid()
    
    get_month_dates()
    
    edge_offset = 9
    drawWord('SUN', x + 0 * spacing + edge_offset, y - 3, 2.5)
    drawWord('MON', x + 1 * spacing + edge_offset, y - 3, 2.5)
    drawWord('TUE', x + 2 * spacing + edge_offset, y - 3, 2.5)
    drawWord('WED', x + 3 * spacing + edge_offset, y - 3, 2.5)
    drawWord('THU', x + 4 * spacing + edge_offset, y - 3, 2.5)
    drawWord('FRI', x + 5 * spacing + edge_offset, y - 3, 2.5)
    drawWord('SAT', x + 6 * spacing + edge_offset, y - 3, 2.5)
    
    drawWord(Months[month], x + 5, y - 10, 5)
    draw_number(100 - 25, y - 15, Math.trunc(year / 1000) % 10, 3)
    draw_number(100 - 20, y - 15, Math.trunc(year / 100) % 10, 3)
    draw_number(100 - 15, y - 15, Math.trunc(year / 10) % 10, 3)
    draw_number(100 - 10, y - 15, Math.trunc(year / 1) % 10, 3)
    
    
    return false;
}