/*  TURTLE GRAPHICS
 *  Direct       | JavaScript       | Description
 * --------------+------------------+----------------------------
 *  FD n         | FD(n)            | Move pen n units forward
 *  BK n         | BK(n)            | Move pen n units back
 *  LT deg       | LT(deg)          | Turn pen deg degrees left
 *  RT deg       | RT(deg)          | Turn pen deg degrees right
 *  UP           | UP()             | Pen up   - move only
 *  DN           | DN()             | Pen down - draw
 *  WIDTH w      | WIDTH(w)         | Set stroke width
 *  COLOR c      | COLOR("c")       | Set drawing color
 */

/* Draws a colored square */

COLOR("red")    FD(10) LT(90)
COLOR("yellow") FD(10) LT(90)
COLOR("green")  FD(10) LT(90)
COLOR("blue")   FD(10) LT(90)
// You can loop over a section of code like so:

REPEAT 12 BEGIN
	FD(10)
	LT(30)
END
// REPEAT loops can be nested:

REPEAT 6 BEGIN
	WIDTH(2) FD(10) LT(60)
	WIDTH(1) RT(45)

	REPEAT 12 BEGIN
		FD(2)
		RT(30)
	END
	LT(45)
END
// Using constants makes the code easier to read and change:

const nr_segments = 12

REPEAT nr_segments BEGIN
	FD(10)
	LT(360/nr_segments)
END
/* Functions group instructions, that can be called from different
 * locations in the program.
 */

function nested_polygon( outer_steps, inner_steps ) {
	const outer_size  = 10
	const outer_width = 2
	const outer_angle = 360/outer_steps

	const inner_size  = 5
	const inner_width = 1
	const inner_angle = 360/inner_steps

	const inner_rotation = (outer_angle + inner_angle)/2

	REPEAT outer_steps BEGIN
		WIDTH(outer_width)
		FD(outer_size)
		LT(outer_angle)

		RT(inner_rotation)
		WIDTH(inner_width)

		REPEAT inner_steps BEGIN
			FD(inner_size)
			RT(inner_angle)
		END

		LT(inner_rotation)
	END
}

nested_polygon(4, 3)
nested_polygon(4, 5)
// Unlike constants, variables can change their contents in run time.

const colors = [                              // Define an array of strings
	"red",  "yellow", "green",
	"cyan",	"blue",	  "magenta",
];

var index = 0;                                // Counts through the colors

WIDTH(5); UP();  RT(90); FD(11.5); LT(90);    // Move down 11.5 units,
BK(2)                                         // centering the circle
REPEAT 12 BEGIN
	index = index + 1                     // Select next color

	// The colors[] array has a range of [0..5] in this example.
	// So we clamp  index  to values from 0 to (colors.length-1).
	// "%" is like "/", but the result is the remainder of the division:
	index = index % colors.length

	COLOR( colors[index] )                // Set the color
	DN()   FD(4)                          // Draw line
	UP()   FD(1) LT(30) FD(1)             // Move to next line
END
// "The code is the documentation."
// - 1337 hax0r

function recurse( distance, angle ) {
	if (distance > 0) {
		FD(distance);
		LT(angle);
		recurse(distance - 1, angle);
	}
}

function multiple( distance, angle, iterations ) {
	for( let i = 0 ; i < iterations ; ++i ) {
		recurse(distance, angle);
	}
}


const selected_variant = 0;

switch (selected_variant) {
	case 1:  recurse ( 20, 30    );  break;
	case 2:  multiple( 20, 30, 3 );  break;
	case 3:  recurse ( 10, 60    );  break;
	case 4:  multiple( 10, 60, 3 );  break;
	default: throw Error("Oopsie...");
}




const angle_reduction  = 0.8
const length_reduction = 0.65
const hex = "0123456789abcdef";

function draw_branch( angle = 50, length = 32 ) {
	if (length < 1) return;

	const brightness = Math.floor((32 - length)/5);
	COLOR("#6" + hex.charAt(brightness+2) + "0")

	WIDTH(length/2)
	FD(length)

	PUSH()
	LT(angle)
	draw_branch(
		angle *angle_reduction,
		length*length_reduction
	)
	POP()

	PUSH()
	RT(angle)
	draw_branch(
		angle *angle_reduction,
		length*length_reduction
	)
	POP()
}

RESET(NO_GRID) BACKGROUND("#030")
LT(90) UP() BK(40) DN()

draw_branch()

HIDE()
/* EcmaTurtle provides you with a set of functions, like FD, REPEAT, etc.
 * Let's take a look, how REPEAT is implemented:
 */

function MyRepeat( times, callback ) {
	while (times > 0) {                                await
		callback();          // Please ignore the "await".
		times = times - 1;
	}
}

/* The function takes another function as parameter (callback) and
 * executes that function repeatedly. It is used like so:
 */

const do_something = async function() {
// My parser can't handle callbacks yet
//...Xunction do_something() {
	FD(10)
	LT(30)
}

MyRepeat(12, do_something);
/* You don't have to declare a function for using it with repeat;
 * instead, use "anomnymous functions", which are declared on the spot:
 */

REPEAT(
	12,
	async function() {   // Ignore the "async" for now
		FD(10)
		LT(30)
	}
);
// Arrow functions can be used in similar fashion to anonymous functions:

REPEAT( 12, ()=>{
	FD(10)
	LT(30)
});
/* In reality, all the code you enter here is JavaScript. Before execution,
 * parts of your code will be replaced with real JS code, for example:
 *
 *	REPEAT 12 BEGIN
 *		FD(10) LT(30)
 *	END
 *
 * will be turned into the following code:
 */

// REPEAT --> "REPEAT("
REPEAT(12, ()=>{          // BEGIN --> ", ()=>{"
	FD(10); LT(30);
});                       // END   --> "});"

/* The take-away of this lesson is, that EcmaTurtle's replacements may do
 * something silly, causing your program to crash. Of course I did some
 * testing and most things will work just fine. If your program crashes
 * for no apparent reason and you suspect EcmaTurtle to be the culprit,
 * you can check the actual code being run; It is dumped to the Developer
 * Console of your browser before execution.
 */




//...SPEED(NO_ANIMATION)

const max_segments   = 15   // 16 hexadecimal digits
const rotation_speed = 5;

BACKGROUND("black")

function draw_circles( nr_segments, rotation ) {
	RESET(NO_GRID | NO_TURTLE | FULL_SPEED)
	LT(rotation)

	const hex_digits = "0123456789abcdef";
	const R = hex_digits.charAt(nr_segments * (rotation % 3 == 0));
	const G = hex_digits.charAt(nr_segments * (rotation % 3 == 1));
	const B = hex_digits.charAt(nr_segments * (rotation % 3 == 2));

	COLOR("#"+R+G+B);

	for( let r=0 ; r<nr_segments ; ++r ) {
		for( let i=0 ; i<36 ; ++i ) {
			FD(2)
			LT(10)
		}
		RT(360/nr_segments)
	}

	RT(360/max_segments)
	SLEEP(33)
	UPDATE()
}

let r = 0
while (true) {
	for( let s=2 ; s<max_segments ; ++s ) {
		draw_circles(s, r)
		r += rotation_speed
	}
	for( let s=max_segments ; s>2 ; --s ) {
		draw_circles(s, r)
		r += rotation_speed
	}
}
const nr_segments    = 36
const radius         = 50

function circle( radius, nr_segments ) {
	const circumference  = 2*radius*π
	const segment_length = circumference/nr_segments

	UP()
	FD(radius) LT(90) BK(segment_length/2)
	DN()

	REPEAT nr_segments BEGIN
		FD(segment_length)
		LT(360/nr_segments)
	END

	UP()
	FD(segment_length/2) RT(90) BK(radius)
	DN()
}

function coordinates( radius ) {
	const length      = 2*(radius+10)
	const dash_length = 2;
	const nr_dashes   = length/(2*dash_length)+1
	const distance    = length/2 + dash_length/2

	LT(90)
	UP() BK(distance) DN()
	REPEAT nr_dashes BEGIN  FD(2) UP() FD(2) DN()  END
	UP() BK(distance+dash_length) DN()

	RT(90)
	UP() BK(distance) DN()
	REPEAT nr_dashes BEGIN  FD(2) UP() FD(2) DN()  END
	UP() BK(distance+dash_length) DN()
}

function triangle(radius, angle) {
	const x = COS(angle)*radius
	const y = SIN(angle)*radius

	FD(x)	LT(90)
	FD(y)	LT(90+angle)
	FD(radius)
	LT(180-angle)
}

WIDTH(1) COLOR("black") coordinates(radius)
WIDTH(4) COLOR("black") circle(radius, nr_segments)
WIDTH(2) COLOR("red")   triangle(radius,  30)
WIDTH(2) COLOR("green") triangle(radius, -45)
WIDTH(2) COLOR("blue")  triangle(radius, 120)
const letter_width = 9;
const letter_gap   = 4;
const curvature    = 5;
const text         = "Hello, World!";

function draw_character( character ) {

	const w = letter_width    // Typical letter width

	switch (character.toUpperCase()) {
	case "H":
		LT(90)  FD(20)
		UP()    BK(10)  DN()
		RT(90)  FD(w)   LT(90)
		UP()    FD(10)  DN()
		BK(20)  RT(90)
	break

	case "E":
		LT(90)  FD(20)  RT(90)  FD(w)
		UP()    RT(90)  FD(10)  RT(90)  FD(3)  DN()
		FD(w-3)
		UP()   LT(90)   FD(10)  LT(90)  DN()
		FD(w)
	break

	case "L":
		LT(90)  FD(20)
		UP()    BK(20)  DN()
		RT(90)  FD(w)
	break

	case "O":
		UP()  LT(90) FD(10)  DN()
		REPEAT 3 BEGIN  FD(4) RT(30)  END
		RT(30)
		REPEAT 3 BEGIN  FD(4) RT(30)  END
		LT(30)
		REPEAT 3 BEGIN  FD(4) RT(30)  END
		RT(30)
		REPEAT 3 BEGIN  FD(4) RT(30)  END
		LT(30)
		UP()  BK(10) RT(90) FD(11)  DN()
	break

	case ",":
		LT(75)  BK(5)  FD(5)

		REPEAT 6 BEGIN  FD(1)  LT(60)  END
		RT(75)
	break

	//case "W":
	//break

	//case "R":
	//break

	//case "D":
	//break

	case "!":
		LT(90)  FD(1)
		UP()  FD(2)  DN()
		FD(17)
		UP()  BK(20)  DN()
		RT(90)
	break

	case " ":
		UP()  FD(8)  DN()
	break

	default:
		COLOR("red")  FD(w)  COLOR("BLACK")
	} // switch

	UP()  FD(letter_gap)  DN()
}

function draw_text( text, angle=0 ) {
	// Move half the text width to the left
	UP()
	REPEAT text.length BEGIN  BK((letter_width+letter_gap)/2) END
	FD( text.length * ((360 - curvature) / 360) )
	DN()

	// Turn left half as much, as the loop below will turn right in total
	const length
	= text.length
	- 1   // The "," has virtually no width
	- 1   // The "!" has virtually no width
	;
	LT( length*angle/2 )

	// Draw each character
	for( let i=0 ; i<text.length ; ++i ) {
		const character = text.charAt(i);
		draw_character(character);

		RT(angle)   // Turn right after each char, creating an arc
	}
}

WIDTH(3)
draw_text(text, curvature)
HIDE()
// Bannkreis
GRID(OFF)
BACKGROUND("black")

const radius = 50
const nr_segments = 360/5
const segment_length = 2*π*radius/nr_segments

COLOR("#642") WIDTH(22)
LT(72*3)

UP() FD(radius) LT(90) BK(segment_length/2) DN()
REPEAT nr_segments BEGIN
	FD(segment_length)
	LT(360/nr_segments)
END
UP() FD(segment_length/2) RT(90) BK(radius) DN()

LT(72*3)

UP() LT(90) FD(16.2) RT(90) BK(50) DN()
COLOR("black") WIDTH(33)

REPEAT 5 BEGIN
	FD(38);
	UP(); FD(2); DN()
	FD(60)
	RT(180*4/5)
END

COLOR("#ca0") WIDTH(1.5)
REPEAT 5 BEGIN
	FD(38);
	UP(); FD(3.25); DN()
	FD(58.25)
	RT(180*4/5)
END

RT(180*1/5/2)
UP() FD(10) DN()
LT(180*1/5/2)

REPEAT 5 BEGIN
	FD(27.5);
	UP(); FD(3.25); DN()
	FD(49.75)
	RT(180 *4/5)
END

HIDE()







// New Program