From ae5ad41f10957f9b5e4c0dbe57f640536b6ff4f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=BCller-Downing?= Date: Sat, 8 Mar 2025 16:05:31 +0100 Subject: [PATCH 01/11] Adds frames for Etienne --- frames/brittany.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++ frames/frames.go | 1 + 2 files changed, 52 insertions(+) create mode 100644 frames/brittany.go diff --git a/frames/brittany.go b/frames/brittany.go new file mode 100644 index 0000000..68ed11c --- /dev/null +++ b/frames/brittany.go @@ -0,0 +1,51 @@ +package frames + +var Brittany = DefaultFrameType(brittanyFrame) +var brittanyFrame = []string{ +`oooooooooooo//////////////////////////////////////////////////////////////////// +ooooooooooooo////////////////oNo//////////////////////////////////////////////// +ooooooooooooooooooooooooooooohdNooooo/////////////////////////////oooooooooooooo +ooooooooooooooooooooooooooooohdddhhNhooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNdNhhhhhhoooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNdNddooohhhNNhooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNddhNhNoooNNNhoNhoooooooooooooooooooooooooooooooo +hhooooooooooooooooooooooooooohsNddodddhhooohoNNhhhoooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdNNoooooohoo/hNohN.NNooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddN////......///hNhoddhoooooooooooooooohhhhooohhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddNNNNNNNNNNh/.../ohNddhoooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhohooooooooooooNdhhhhhhhNNNdNoo//..//oNooooooooooo////o////////// +//////////////////////////////Ns/..........////ooo/../h///////////////////////// +//////////////////////////////hdhhhhhhhhoooo/.../ohh/./Nh/////////////////////// +//////////////////////////////odNNNNNNdddddssNo..../ho./ddNo//////////////////// +///////////////////////////////h/.......///////oo/...ho..ohNN/////////////////// +///////////////////////////////No/////..........ohh/./hh/../o/////////////////// +////////////////////oooohhhhNNNddhhhhhhhhhhhooooo//oohhNNNhhhhhhhooooo////////// +/////oohhNNNdddssssssddddNNNNhhdsNhoooooooooooooo/./hh/oohhhhNNNNNNddddddddddddN +ddssssddNNNhhooo///////////////hsh///////////////////o////////////////////////o/ +ooo///////////////ooohhhNNNNdddd-sdddddddddddNNhhho/hdddddNNNNNhhhhoooo///////// +/////oohhNNdddss----------ssssss-ssssssssssssddddNhhdddddssssssssssssssssssssddo +/hNds----------sssddddssssss----- ----------sdddNhdsssssssddddddssdddddddddssh`, +`ooooooooooooo//////////////////////////////////////////////ooooooooooooooooooooo +oooooooooooooooooooooooooooooNNoooooo///////oooo/ooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooNdNhooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooddNhhNhoooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooodNdhoNhhhNNhooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooosddNhNhhhhhhhNhhooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsddNhhoNNh/ohhhoNNNhooooooooooooooooooooooooooooohh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsdsNodNNoddNhohhNhNh/ooooooooooohhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsddhohhhohNdhohhh/hNhhhNhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhddh/./......////////ooohdNhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddNNhNhhoooo//o/......./ooooohhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhooooooooooooooohddNNNNNddNNNNNNNddNhhhoooo//..//ooooooooooooooooooo +/////////////////////////////NN...........////ohooooohhhhhhooohhhh////////////// +/////////////////////////////NNhhhhooooo///..............//oohhhhNdh//////////// +/////////////////////////////hNdddddddddddNNNhhhooo////.........../o//////////// +/////////////////////////////h/..////////ooooohhhhhhhhhhhhhhoooo//.../////////// +/////////////////////////////oo/////////............/////ooohhhhhhhhoh////////// +////////////////oooohhhhhhhhhhdhoooooooooooo//////////..........//oohh////////// +ohhNNddddssssssssdddddNNNNNNNNsdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhooo////ohhhooo///// +ddNNNhhooooo//////////////////sd///////////////////////////////oo///hhNNNddddddN +/////////////ooohhhhNNNNNNNdNNs-dNNNNhhhhhhoooooooooooo///////////////////////// +oohNNNddsss--------------sssss-ssssssssssssssssddddddddddddssssddddNNhhhhoooo/.. +----------sssssddsssssssssss-------ssssssssssdddddddddddddddddddsss-----sssddh..`, +} diff --git a/frames/frames.go b/frames/frames.go index f4c29f5..c4146b1 100644 --- a/frames/frames.go +++ b/frames/frames.go @@ -63,4 +63,5 @@ var FrameMap = map[string]FrameType{ "earth": Earth, "kitty": Kitty, "india": India, + "brittany": Brittany, } From 689a5d76f20a79dd71a6a6477f2a43dda9bf670f Mon Sep 17 00:00:00 2001 From: Salazar2244 <157654504+Salazar2244@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:45:45 +0100 Subject: [PATCH 02/11] Add the Brittany's Flag Closes #76 --- frames/brittany.go | 421 +++++++++++++++++++++++++++++++++++++++++++++ frames/frames.go | 1 + 2 files changed, 422 insertions(+) create mode 100644 frames/brittany.go diff --git a/frames/brittany.go b/frames/brittany.go new file mode 100644 index 0000000..75d8ee7 --- /dev/null +++ b/frames/brittany.go @@ -0,0 +1,421 @@ +package frames + +var Brittany = DefaultFrameType(brittanyFrame) + +var brittanyFrame = []string{ + `hhhoohhooooooooooo////////////////////////////////////////////////////////////// +hhhhoooooooooooooooo////////oNo///////////////////////////////////////////////// +oooooooooooooooooooooooooooooNNooo////////////////////////////////////////oooooo +oooooooooooooooooooooooooooohddhNooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsdNoNhooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsdshhhdhooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsdsNoooNhoooooooooooooooooooooooooooooooooooooooooo +hhhhhhhhoooooooooooooooooooohsNsdohhhodNoooooooooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNdhooooohhhhoooooooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNN///..../hshhhhhhhhhhoooooooooooooooooooooooooohh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNNNhhhoo///hdNhhoooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNNNNNdNhhhho/hdhoooooooooooooooooooooooooooooooooo +o/oo/////////////////////////dN/.........././ho///////////////////////////////// +/////////////////////////////ddooooooo//..o/./////////////////////////////////// +/////////////////////////////ddddddddddhhhhNo./../////////////////////////////// +/////////////////////////////No//////ooo////..//..////////////////////////////// +/////////////////////////////ho////////......../h/////////////////////////////// +//////////////////////ooooooohdooooooo/////////NNd//////////////////////./////// +//oohhhNNNdddddssssssssssdddddsdNNNNhNNhhhhhhhNdNddNsssdddddddNNNNhhhhooo/////// +sssddNNNhhhhooooo////////////osdo////////////////./N/////oooooohhhhhNNNdddsssddN +//////////////////oooohhhhhhhNsshhhhhoooooooooooo/.ooo/////////////////////////o +//oohhhNNdddsss--------------s---------sssdNNNNNdN/Ns-----sssdddNNNNhhooo/////oo +ds-----------ssssssddddsssssss--ssssssssdddddddddN/dddddddddsssss--------sssdNhh`, + `hhhooooooooooooooo////////////oo//////////////////////////////////////////////// +ooooooooooooooooooooooooooooooNdo///////////////////////////////////////////ooo/ +ooooooooooooooooooooooooooooooNdNhoooooooooooooo//////////o/o/oooooooooooooooooo +ooooooooooooooooooooooooooooooddsNNhoooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNsdNNhhoooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooooddddNNhNNhoooooooooooooooooooooooooooooooooooooooo +hhhoooooooooooooooooooooooooooddNdhddNNoNNoooooooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhdhNdshohNNooooooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhh////ooo/NhNNhhhhohooooooooooooooooooooooooooho +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhh//////./ohNhhNhhhhooooooooooooooooooohhoohhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhddddddddN/...../ooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooooNsoooooohhNNNho//.../ooooooooooooooooooooooooooooo +//////////////////////////////Ns/..........////hhoo/./////////////////////////// +//////////////////////////////NdNNNNNNNhhhhoo/..//ohho////////////////////////// +//////////////////////////////hNhhhhhNNdddssssdho/...oNo//////////////////////// +//////////////////////////////ho/........///ooooooho/..ho/////////////////////// +//////////////////////////////oNo/////////......../ohho/No///////./.....///////. +///////////ooohhhhNNNNNddddddddsdNNNNNhhhhhhhhNNNh//.oohho////////////////////// +NNddddssssssddddNNNNhhhhhhhoooosdhoooooooooooohhhhh//...hN/ddsssssdddddNNNhhhoo/ +Nhhhoooo//////////////////////odso/////////////////////..oh////////ooooohhhNNddd +//////////ooohhhNNNNddddsssssss--ssssssdddddddddddNNhhooo///oo////////////////// +hhNdddss------------ssssssssssssssssssssssssssssssssssddNNood-----sssddNNhhhooo/ +------ssssddddddsssssss----- -----------sssssddddddNddddddssss--------ss +`, `ooooooooooooooo///////////////////////////////////////////////////////////////// +oooooooooooooooo//////////////oo//////////////////////////////////////////////// +ooooooooooooooooooooooooooooooddooo/////////////////////////////////////oooooooo +ooooooooooooooooooooooooooooooNdNooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooooddshoNNNhooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNsdhhohhdNhoooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNddNN/hhhhdddhooooooooooooooooooooooooooooooooooo +hhhhhhooooooooooooooooooooooooddNdNNhhooohhNdhNhoooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddhNhNdN/hhhooNooNNooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddho//////////oo/o////ooooooooooooooooooooooohoooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhNshhoooo///....../oo/.//hooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhNshdddddddNhhooooo//oo../NNooooooooooooooooooooooo +oooooooooooooooo//o//o/o//o/ooNso////ooo///oooooohhhho/.Ndo//o////////////////// +//////////////////////////////hso/////............/ohhhhoNd///////////////////// +//////////////////////////////hdddddddddddNhhhoo///./ohhNdd///////////////////// +//////////////////////////////oNooooohhohhhoooooooho.../ohdh///////.//////////// +///////////////////////////////o//................./o...../hN/////////////////// +///////////////////////////////Nh//////////////...../hoo/.../o/////.....//////// +///////oohhhNNNNNdddddsssssssssssdNNNNNNNNNNNNNNNhhh/ohhhhoNNNNhhhhoooo///////// +dddssssdddNNNhhhhhoooooo///////Nso///////////////////..//ohoohhhhNNNddddsddddddN +ooo/////////////////////oooooooNshoooooo//////////////....///////////////////ooo +//////ooohhNNNdddssss------------------------sssddNNNhhhhNddddNNNhhhoooo//////// +ohNds-------------ssssssddddddss-ssssssdddddddddddddddddddssss---------sssddNhho +`, `oooooooooooo//////////////////////////////////////////////////////////////////// +ooooooooooooo////////////////oNo//////////////////////////////////////////////// +ooooooooooooooooooooooooooooohdNooooo/////////////////////////////oooooooooooooo +ooooooooooooooooooooooooooooohdddhhNhooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNdNhhhhhhoooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNdNddooohhhNNhooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohsNddhNhNoooNNNhoNhoooooooooooooooooooooooooooooooo +hhooooooooooooooooooooooooooohsNddodddhhooohoNNhhhoooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdNNoooooohoo/hNohN.NNooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddN////......///hNhoddhoooooooooooooooohhhhooohhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhddNNNNNNNNNNh/.../ohNddhoooooooooooooooooooooooooo +hhhhhhhhhhhhhhhhohooooooooooooNdhhhhhhhNNNdNoo//..//oNooooooooooo////o////////// +//////////////////////////////Ns/..........////ooo/../h///////////////////////// +//////////////////////////////hdhhhhhhhhoooo/.../ohh/./Nh/////////////////////// +//////////////////////////////odNNNNNNdddddssNo..../ho./ddNo//////////////////// +///////////////////////////////h/.......///////oo/...ho..ohNN/////////////////// +///////////////////////////////No/////..........ohh/./hh/../o/////////////////// +////////////////////oooohhhhNNNddhhhhhhhhhhhooooo//oohhNNNhhhhhhhooooo////////// +/////oohhNNNdddssssssddddNNNNhhdsNhoooooooooooooo/./hh/oohhhhNNNNNNddddddddddddN +ddssssddNNNhhooo///////////////hsh///////////////////o////////////////////////o/ +ooo///////////////ooohhhNNNNdddd-sdddddddddddNNhhho/hdddddNNNNNhhhhoooo///////// +/////oohhNNdddss----------ssssss-ssssssssssssddddNhhdddddssssssssssssssssssssddo +/hNds----------sssddddssssss----- ----------sdddNhdsssssssddddddssdddddddddssh +`, `ooooooo//////////////////////oh///////////////////////////////////////////////// +oooooooooo///////////////////hdh//////////////////////////////////////////////// +ooooooooooooooooooooooooooooohddhoooo////////////////////////////o/ooooooooooooo +ooooooooooooooooooooooooooooohdsNhddNhhhoooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohdNdhhhdhNNNhNNhhhooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohshdNNoNdsNNhhhhohdo//ooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohshdNhhNhdhNddhohhhhhhhho//oooooooooooooooooooooooo +ooooooooooooooooooooooooooooohshNhNNN/NdsdNsdNhh/.../oo/./oooooooooooooooooooooo +hhhhhhhhhhhhhhhhhhhooooooohhhhsNh///oohhNhhdsdoNhoo///....//oooooooooooooooooooo +oohhhhhhhhhhhhhhhhhooooohhhhhhdNho/.......///oohhhhhhhhoooo/./oooooooooooooooooo +hhhhooooooooooooooooooooooooohdNhdddhhhhooo/o//////...//////../ooooooooooooooooo +ooooooooooooooooooooooooooooooddoohhhhhNNhhhNNdddNNNNho////....hho////////////// +//////////////////////////////Nd/...../......//ohNNNdddNNhhhh//oo/////////////// +//////////////////////////////NdNNhNNhhhhhoooo///...............//////////////// +//////////////////////////////hhhhhhddNNNddssssdNhhoooooooooooooho////////////// +//////////////////////////////o/....../...../////o/////ooohhhNhhhNN///////////// +//////////////////////////////oNo/////./////.......///............////////////// +//////////////ooohhhNNNNNNddddNdNNNNNNNhNNNNNhhhhhhNNNNNNNNNNhhhhhooooo///////// +/oohNNNdddsssssdddNNNhhhhhooooodso///////////////oooooooohhhhhhhNNNNdddddddddddN +sddNNhhooo/////////////////////Nso///////////////////////////////////////////ooo +/////////////ooohhhNNNddddssssss-ssssddssssssssssssssddddddNNNNhhhhoooo///////// +//ohhNNddsss--------ssssssssssss-sssssssddddddddddddddddddsssssssss-ssssssssddNN +s---------sssdddddddsssss---- - -------------sssssddddddddsdddddddssss- +`, `ooo///////////////////////////ho//////////////////////////////////////////////// +ooo//////////////////////////odNo/////////////////////////////////////////////// +oooooooooooo/////////////////oNdNhhho/////////////////////////////////////////oo +oooooooooooooooooooooooooooooodNdNohNhhooooooo///////////o/o/ooooooooooooooooooo +oooooooooooooooooooooooooooooodNdNhNhh/NNhhhoooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNdNNhohhhohNNNhohoooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNNNhdNdNhoooohoNhNNNhoooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooodNNhoNdNhodNh/hhhoN//ohhhooooooooooooooooooooooooo +ooooooooooooooooooooooooooooohddh/....///////oo/hNho/////ooooooooooooooooooooooo +ooooooohhhhoooooooooooooooooohddhoo///////......../ooohoo//ooooooooooooooooooooo +ooooooooooooooooooooooooooooooNdhddNddddNNNNhhooo///...//ohh//oooooooooooooooooo +ooooooooooooooooooooooooooooooNdo/ooooooooooohoooooooohho../o////oo///////////// +//////////////////////////////hd......................//ohho/.ohh/////////////// +//////////////////////////////hddNNNNNNNNNNhhhooo///......./ohooohNo//////////// +///////////////../////////////oNhhhhhhhhhhhhNNNdddhhhhoooooo/../hhNd//////////// +//////////////////////////////o/................///////////oho/../h///////////// +///////////////////////////////Nh/////////...................ooo..////////////// +/////////////ooohhhNNNNNNddddddddNNNNNNNNNNNhhNNNNNNhhhoooo/..hhooooo/////////// +ohhNNddddssssddddNNNhhhhhoooooodso//////////////oooooooooooo//hhNNNddddddddddNNN +ddNNhhooo//////////////////////Nso//////////////////////////////////////////oooo +////////////ooohhhNNNNddddssssss-sssssssssssssssssddddNNhhhhhhhhhoooo/////////// +/ohhNNddsss--------ssssssssssssssssssdddddddddddddddddddddddsssssss-ssssssdddNNN +--------ssssdddddddddssss---- -- -------------sssssddddddddddsddddddsssssd +`, `/////////////////////////////hh///////////////////////////////////////////////// +o////////////////////////////NNo//////////////////////////////////////////////// +oooooooooooo////////////////oNdNho//////////////////////////////////////////oooo +oooooooooooooooooooooooooooooddNhhNhoooooo////////////////oooooooooooooooooooooo +oooooooooooooooooooooooooooooddNhoohNhoooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooddshooohhNhhooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooddddoohoooddNhhoooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooodddNoohoohhhoNNo//ooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooNdN/.....//hNNNho/.//oooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooNshhooo///./h/hddNNo////ooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooNsNddddNhhhoo/oNddssNhoo//ooooooooooooooooooooooooo +ooooooooooooooooooooooooo//o/hs//////////oh.../hNdsdNo/oo/////////////////////// +/////////////////////////////hd//////....../....../ohdN/..//./////////////////// +/////////////////////////////odddddddddhhooo/oNo//...//hho/.//////////////////// +///////////...../////////////ohoooooohhhoooohhNdNhhhho/.oNdh/////////..../////// +//////////////////////////////o/............../hh//oNddNh/////////.....///////// +//////////////////////////////Nh////////........//.../ohNdo///////////////////// +/////////ooohhhNNNNdddddddddddddNNhhhhhhhhhhhhho/.//oooooho/..ohhhoooo////////// +NNdddssssdddNNhhhhoooooo//////Nso///////...//////////////..//ohhhNNNNddddddddNNN +hhooo///////////////////////oohsh///////////////////.////////////////////////ooo +////////ooohhhNNNdddssss------s--ssssssssddNNNNNNNNhhhNNNdddNNNhhhhoooo///////// +hNNddss------sssssssssssddsssss-ssssssssdddddddddddddddddddddddssssssssssssdddNN +----ssssdddddddddsss---- -- -sssssdds--sssssdddddddsdddddddddsss- +`, `////////////////////////////hN////////////////////////////////////////////////// +////////////////////////////hdho//////////////////////////////////////////////// +oooooooo////////////////////hdsNhhhoo///////////////////////////////////oooooooo +ooooooooooooooooooooooooooooNNddoohhhNNhoooooooo/oo/oooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdNddNhooohhhhNNN/hhoooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohdhNNNN/hoo/hhNohhhhhNNhhooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsoNNhddNohohoooohhN/..//ooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohshhhoNNNohhh/ohho/hhhho/..../oooooooooooooooooooooo +oooooooooooooooooooooooooooohsh/.........////////ooohhhoo/./hhhooooooooooooooooo +oooooooooooooooooooooooooooohshhhhooooo///.............//oooo/hNNhoooooooooooooo +oooooooooooooooooooooooooooohdNNdddddddddNNhhhhhhooooooo//.../..oNNhoooooooooooo +ooooooooooooooooooooo///////odh.////////ooo/////oooooooohNNho/.../////////////// +/////////////////////////////Nh///////....................//ohNh/o////////////// +/////////////////////////////NNdddddddddddddNNNNNhoooo/////.../oNh////////////// +/////////./....//////////////hoooooooooohhhhhhhhhhNhooooooooho/..///////./.../// +/////////////////////////////o//............................./hho../////////..// +/////////////////////////////oNo////////////////.............../h//////...//.... +//////////oohhhNNNNdddddddddddddNNNNNNNNNNNNNNNNNNNNhhhhhhhhho/hNNNhhhhhooo////. +hNNdddssssddNNNhhhoooo////////dd///////.............../////////ooooohhhhNNNddddN +Nhhooo/////////////////////oooNsoooo//////////////////////////////////....../.// +/////////ooohhhNNdddssss-----ss----------s------sssdNNNNNNNddddNNNNNhhhoooo////. +ohNNddss-----ssssssssssdddsssss-ssssssssssssssddddddddddddddddddddsssssssssssssN +-----ssssddddddddsss---- - -dddds-sssssddddsddddddddddddd +`, `////////////////////////////dh////////////////////////////////////////////////// +////////////////////////////NNo///////////////////////////////////////////////// +ooooo//////////////////////oNdNNho///////////////////////////////////////////ooo +oooooooooooooooooooooooooooodNdhNdhooo//////////////////////////oooooooooooooooo +oooooooooooooooooooooooooooodNdNNdhdNooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooodNdNhNhNddhhoooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooodNNNoNddhNNddNhooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooddhhohhhhhNhdddh/ooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdh/......//hNsdo/./oooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdhhhhoooooohhNN//..../ohooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNshNNNNNNNNdddNNdNo/..../NNooooooooooooooooooooooooo +ooooooooooooooooooo/////////hd/.......////oooNdsNo....oNN/////////////////////// +////////////////////////////odo////////........ohNNoo/.///No//////////////////// +////////////////////////////oNNNNNNNdddddNNNNNo.../////ohNdNN/././..//////////// +/////////////////////////////h//////oooohhhhNNNhooo//.........////////////./.../ +/////////////////////////////o/................../oNddNdNNhhN//../....///....... +/////////////////////////////Nh///////////////......./ooooo//.////////////////.. +////////ooohhhNNNNddddddddddddsNNNhhhhhhhhhhhhNNdddddddddNNNNNNNNNhhhhoooo/////. +NNdddsssdddNNNhhooooo////////hso/////////.............////////ooooohhhhNNNddddd/ +hhoo/////////////////////oooohsNooo//////////////////////..///////////..//////// +/////////oohhNNNdddsss------ss--ssssssssssssss-ssssssssssssddddNNNNhhhooooo///// +hhNddss-----ssssssssssddddssssssssssssssssssdddddddddddddddddddddsssssssssssssdo +----sssdddddddddsss---- - -------ssssdddddsdddddddNdddddo +`, `////////////////////////////ho////////////////////////////////////////////////// +///////////////////////////oNNo///////////////////////////////////////////////o/ +oooooo/////////////////////oNdhho////////////////////////////////////////ooooooo +ooooooooooooooooooooooooooooddNohNoooo/////////////////////////ooooooooooooooooo +oooooooooooooooooooooooooooodNNhhohNNooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooodNdhhh/hNNhhoooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdNdNoNdooohNdhoooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdNNhoNNNohhooNhNhooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdNN....//////hNNNhoooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooddhooo/////.......//oooooooooooooooooooooooooooooooh +ooooooooooooooooooooooooooooddNdddNNNNNdNoo//....///oooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNd///////oooohoooohhoohhooo///////////////////////// +////////////////////////////hd/................//ohNdNddNNh///////////////////// +////////////////////////////hdNNdddNNNNhhhhoo/////../o/ohNddN/////////////////// +////////////////////////////ohoohhhhhhhhhNNNNhhhhhhoo/......//////////////////// +////////////////////////////o/....................//ohhoohhhhoo//////.//..../... +/////////////////////////////No///////................/ohNdNNNdh///////../////// +//////////ooohhhNNNNNdddddddddNNNhhhhhhhhhhhhhhhhhhho/../oooooohhoooo/////////// +hNNdddssssddNNNhhhhoooooo////Nd///////........////////..../ooohhhNNNNdddddddNNNo +Nhhooo///////////////////////hso///////////////..................////....////oo/ +/////////ooohhhNNNdddsssssssss-ssssssssssssssssdddNNNhhhhhhNNhhhhoooooo///////// +hhNNddss------ssssssssssddddsdssssssddddddddddddddddddddddddddssssssssssssdddNNo +-----sssdddddddddssss----- -- ----------ssssssdddddddddsdddddddddsssso +`, `////////////////////////////oh//////////////////////////////////////////////oooo +////////////////////////////hdo///////////////////////////////////////////oooooo +oooooooooooo//////////////oohdNhohoo///////////////////////////ooooooooooooooooo +ooooooooooooooooooooooooooooNdNhhhNhhhoooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdNhhNNo/hNhohhooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdNNhhdNhooo/hhNohhooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNdNhhohNd/ohhhohohNNNNhooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooNsNNhhhoddNooo/oohh//oNNNhoooooooooooooooooooooooooo +ooooooooooooooooooooooooooohNsN/.oo/hNdoNNhooho......ooooooooooooooooooohhhhhhhh +hhhhhhhhhooooooooooooooooohhNsNo///.../ohhh/ohhhhoo//...//ooooooooooooohhhhhhhhh +ooooooooooooooooooooooooooooNsNdNNNNNo/////...//oohhhhhooooooooooooooooooooooooo +oooooooooooooooooooooooooooohdo/o/hhhNNNhoohoo/......//oohhNdNNh//////////////// +////////////////////////////od/......../oooohddNhoo//....../oohdNo////////////// +////////////////////////////oNddNNdhhhhooooo//oooooohhhooo//...../////////////// +/////////////////////////////hhhhohhooooohNdsdo.......//oohhhhoo/.////////////// +/////////////////////////////o/............/ohNNhooo//......///oo///////........ +/////////////////////////////Nh/////////........oohNhhhhooo//..../////////////// +/////////ooohhhNNNNNdddddddddddNNNNNNNNNNNhhhhooo///hNNNNNNNNNNo////////../..... +NddddssssdddNNNhhhhooooooooooNso////////////////oooooohhhhhNNNNdddddddddNNNNhhoo +hhooo////////////////////////hsh///////////......////.............//////oooohhho +////////ooohhhNNNddddsssssssss--ssssssssddddNNdddddddNNNNhhhhooooo////////////// +hNdddss-------ssssssssssssddddsssssdddddddddddddddddddddssssssssssssssdddNNhhhho +----sssddddddddddssss----- -- ---------ssssssdddddddddddddsdddddsss---ssh +`, `ooooo//oo///////////////////////////////////////////////////////oo/ooooooooooooo +oooooooooooooooooo/////o/o/ooNho//////////////////////oooooooooooooooooooooooooo +oooooooooooooooooooooooooooooddhoooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohdsdhNhhoooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohdddhhdNNNhooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohdNdNdNhdddNhNhhoooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohshdNhNhdNdhddNhhhhooooooooooooooooooooooooooooooooo +hhhhhhhhhhhhhhhoooooooohhhhhhshNhodddhdssddNhNhoooooooooooooooooooooohhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhshhohhhhoNNdNNssNhhoohNNhoo/oohhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNo/////.//////ohhhho/.//hNNho///ohhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhshNNNhhhhhoooooo//////ooo/..ohNho./hhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhdhNNdddddddddddsssddNh//ohhho/.oNho/ooooooooooooooo +/////////////////////////////do...../////oooohhNNddsh/../oNh..oh//////////////// +/////////////////////////////dhoo//////............/oho/...oNh////////////////// +/////////////////////////////NNNNNNNNNNNNNNNNhhhhhoo../oho/../////////////////// +/////////////////////////////h///////oohhhNNNNNdddssd.../oo///////////////////// +/////////////////////////////ho//...............////ooo/...////.///////...////// +//////////////////oooooohhhhhNNoooooo////////////..../ooo/////////////////////// +oohhNNNddddssssssssdddddddNNNdsNhhhhhhhhhhhhhhhhhhNhNdddddddddNNNNhhhhoo//////// +dddNNhhhhoooo////////////////osN///////////////////////////ooooohhhhNNNdddddddN. +///////////////ooohhhhhNNNNNNN-dhhhooooooooooooooooo///////////////////////////. +oohhNNNddsss--------------ssss-sssssssssssssssssss---ssssssssdddNNNhhhooooo///// +-----------sssssdddddsssssssss--sssssssssddddddddddddddddddddssss------ssddddNN/ +`, `ooooooooooooo//////////////////////////////////////////////ooooooooooooooooooooo +oooooooooooooooooooooooooooooNNoooooo///////oooo/ooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooNdNhooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooddNhhNhoooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooodNdhoNhhhNNhooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooosddNhNhhhhhhhNhhooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooohsddNhhoNNh/ohhhoNNNhooooooooooooooooooooooooooooohh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsdsNodNNoddNhohhNhNh/ooooooooooohhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhsddhohhhohNdhohhh/hNhhhNhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhddh/./......////////ooohdNhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhdddNNhNhhoooo//o/......./ooooohhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhooooooooooooooohddNNNNNddNNNNNNNddNhhhoooo//..//ooooooooooooooooooo +/////////////////////////////NN...........////ohooooohhhhhhooohhhh////////////// +/////////////////////////////NNhhhhooooo///..............//oohhhhNdh//////////// +/////////////////////////////hNdddddddddddNNNhhhooo////.........../o//////////// +/////////////////////////////h/..////////ooooohhhhhhhhhhhhhhoooo//.../////////// +/////////////////////////////oo/////////............/////ooohhhhhhhhoh////////// +////////////////oooohhhhhhhhhhdhoooooooooooo//////////..........//oohh////////// +ohhNNddddssssssssdddddNNNNNNNNsdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhooo////ohhhooo///// +ddNNNhhooooo//////////////////sd///////////////////////////////oo///hhNNNddddddN +/////////////ooohhhhNNNNNNNdNNs-dNNNNhhhhhhoooooooooooo///////////////////////// +oohNNNddsss--------------sssss-ssssssssssssssssddddddddddddssssddddNNhhhhoooo/.. +----------sssssddsssssssssss-------ssssssssssdddddddddddddddddddsss-----sssddh.. +`, `ooooooooooo////////////////////////////////////////////////ooooooooooooooooooooo +oooooooooooooooooooooooooooodhooooooo///oo/ooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooooddNhoooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdddhNNhohooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdNdhhNhohNNhhooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohshdNNNhddhhooNNNhhoooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohshNdhNhNhdNNhohhoNhoooooooooooooooooooooooooooooohhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhshNNoNdN/dssNoohhNoooo//oooooooooohhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhsNooooooohhhhhNNoh//.....//ohhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhsNo///../..../////ohhhhoo//./ohNhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhsNNddNhhhhhhhoohoo..///ohNNNh/../hhhhhhhhhhhhhhhhhhh +hhhhhhhhhhooooooooooooooooohdhhhNNNNNNNNNdddssdNho/..../ohho../Nhooooooooooooooo +////////////////////////////do............///ohhohhhoo//.../ooooh/////////////// +////////////////////////////dhhhhoooooo///..........///ohoo/.../o/////////////// +////////////////////////////NNNNNddddddddddddNNNNho/...../oooo////////////////// +////////////////////////////o/.....////ooohhhNNNddsNho//..../o////////////////// +////////////////////////////hh//////..............////ooho/../////////////////// +////////////oooohhhhhhNNNNNNNdhhooooooooooooooo///////...oho//////////////////// +hNNdddsssssssddddNNNNNNhhhhhNsNoooooooooooooohhhhhNNNNNhoNddsdddddNNNNNhhooo//// +NNhhoooo////////////////////osN/////////////////////////////////oooohhhNNNdddddd +//////////ooohhhhNNNNdddddddd-sdNNNhhhhhhhhhhhhhhhhooooooooo//////////////////// +hNNdddss-------------ssssssss-ssssssssssssssssssssssddsssssssssssdddNNhhhoooo/// +-------sssssdddssssssssss------------ssssssssdddddddddddddddddddssss-----ssddddh +`, `oooooooooo////////////////////////////////////////////////oooooooooooooooooooooo +ooooooooooooooo/oo//ooooooohNooo/o/////////////ooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdhoooooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooNsdNNhooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooodNsN/Ndhooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooodNNdNhooNhhoooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooodNNdNh/hhhddhoooooooooooooooooooooooooooooooooooohhhh +hhhhhhhhoooooooooooooooohhhddhdoNNhohNhdhNhoooooooooooooooohhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhddhhoNNh/oNoNNddhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhddo////...//hNNossNhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhNdhhhhhoo//../ooNsssNhooohhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhNdNddddddhhhhho/./ohNdssNh//ooooooooooooooooooooooooo +ooooooooooooooooooo//////ooNN////////////oho/.////ohdsdho/////////////////////// +///////////////////////////hN//////......../ohhho/////ohddo///////////////////// +///////////////////////////oNddddddddNhooooo//NddddNho/../h///////////////////// +///////////////////////////ooooooooohhoooooohh/ohNNdddddNo.///////////////////// +////////////////////////////o//............../h/..../ohhNNo///////////////////// +//////////////////////////ooNh/////////////....hho//..../o////////////////////// +///oohhhNNNdddddsssssssssssdddNNNNNNNNNNNNhhhhoodddddNNNddddNNNNNNhhhooo//////.. +ssssdddNNNhhhooooooo//o/////Ns///////////./////.///oohho//oooohhhhNNNNNdddddd... +////////////////////oooohhhhN-Nooooooo////////////////////////////////////////.. +///oohhhNNdddsss------------s---------ssddNNNNNNNNNNNNdssssddddNNNhhhhooooo///// +dss-------------ssssssdddssss-sssssssddddddddddddddddddddddsssss------sssdddddoo +`, `ooooooooooooooooooo////ooooooooo////////////oooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooohdoooooooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooohsdhoooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooNdshhNNhhooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooNNdd/hhhhdNhoooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooNNNddhohhhhhhNhhooooooooooooooooooooooooooooooooooohhh +ooooooooooooooooooooooooohNdNdhNohoh/hhNoNdNhooooooooooooooooooohhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhNdhNoddhoNhhohhhhhdooohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhNdhoooNhohhh/hhNh/Nhohhoohhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhNdh//.///...////ooohNNdsdNhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhNdhdNNhhhoo//......../oohdssNhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhNNhNNdddsssdNhhhhoooo//..../hNNooooooooooooooo///ooooo +oooo//////////////////////hN/...///ooohhooohhhhNNhho/.///oo///////////////////// +//////////////////////////oNhooo///............//ohNNNhhhho///////////////////// +//////////////////////////oNNhNdNdsdNNNNhho///....../ohNNdssNho///////////////// +///////////////////////////o/..//ohhhNNddddNhhhhhho//.../ohNdssdo/////////////// +///////////////////////////ho////........./////ooohNNhho...../ohNh////////////// +//////////////oooohhhhhhhNhNNhooooooooo/////......../ohNNho/...../////////////// +hhNNddddssssssssdddddNNNNNNdshhhhhhoooooooohhooooo//.../ohNddNhhoNNNNNhhhooo//// +dNNhhhhooo/////////////////hsh///////////////////////...../hNNNNooohhhhNNNddddd. +////////////oooohhhhNNNNNNNN-dNhhhhoohoooooooooooooooo///...///////////////////. +ohhNNddsss--------------ssss-ssssssssssssdddddddddddddNdssddssssdddNNhhhhoooo/// +----------sssssddsssssssssss----ssssssssssdddddddddddddddddddddssss-----sssddsN/ +`, `oooooooooooooooooooooooooooooooo/////////ooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooodNooooooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooddNoooooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooNshdNhooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooohNdNNdhhhooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooohNNdhhohNNhooooooooooooooooooooooooooooooooooooooohhhh +ooooooooooooooooooooooooohhNNdhoNNhohhhhoooooooooooooooooooooohhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhdhhdNoodhohNhhhohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhdhooh/hhNhohooh//ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhNho////oNNhohhohhooohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhNhNddNNohNhohh.../ohhhohhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhoooooooooooooNhohNddN./ohNNho//../hNo/oooooooooooooooooooo/ooooooo +///////////////////////////No.....//..../oohhhoo/.oo//////////////////////////// +///////////////////////////hhhooo/../o/.....//ohNNo/oo////////////////////////// +///////////////////////////hhhNddNNNNohhho/......ohdhhh///////////////////////// +///////////////////////////o/.//ooohdh./hNNhho/.....oNNN//////////////////////// +///////////////////////////oh///...../...//ohhhhho//..odd/////////////////////// +///////////oooohhhhNNNNNNNNNdhhooooo/.oho/....//ohhhNhoNNhoo//////////////////// +NNNdddsssssssdddNNNNNhhhhhhhdNooooooo/.hhNNho/...../ohNhhddddssdddddddNNNNhhhoo/ +NNhhhooo//////////////////ooNN//////////.//ohNhho//....o///////////ooooohhhNNNN. +///////////ooohhhNNNddddddddddNdNNNNNNNho/.../oohNhhhooohoooooo////////////////. +hhNNddss-------------ssssssssssssssssssssdNho/////ooNdssssssssssssssddNNNhhhhho/ +-------ssssssddsssssssss----s -------sssssdddNhoooohNNddddddddddsddsss-----ssdh/ +`, `ooooooooooooooooooooooooooooNooooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdhoooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdNoooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohsNhooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohdsdooooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooooohNddNooooooooooooooooooooooooooooooooooooohhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhNNshhhhhhhooooooohohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsNhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhh//sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhoodNNhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +hhhhhhhhhhhhhhhhhhhhhhhhhhhhhNshNdhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +ooooooooooooooooooooooooooooh/o//hhoooooooooooooo////oo//oo/ooo/o////////ooooooo +////////////////////////////h....od///////////////////////////////////////////// +////////////////////////////Nhhh.hs///////////////////////////////////////////// +////////////////////////////hohd/Nso//////////////////////////////////////////// +////////////////////////////o..//dso//////////////////////////////////////////// +////////////////////////////oo/.oddo//////////////////////////////////////////// +/////////oohhhhNNNdddddddddNho/.odd//sddddddddddddddddNNNNNNNhhhhoooo/////////// +NdddssssssddNNNhhhhoooooooo/o/..hdd..N////////////oooooooohhhhhNNNNdddsddddddNN. +Nhhooo//////////////////////////hNh//do///////////////////////////////////ooooo. +////////oohhhNNddddssss---sdNho/NN///ss--------ssssssssddddNNNNhhhhhooo///////// +hNddss----------ssssssssssssddNoNo//hdNNdddddddddddddddddddsssss-ssssssssssddNNh +------ssssdssssssss------ ssdhh///NdhN----------sssssdddddddddsddddddddssss--s +`, +} diff --git a/frames/frames.go b/frames/frames.go index f4c29f5..c957144 100644 --- a/frames/frames.go +++ b/frames/frames.go @@ -63,4 +63,5 @@ var FrameMap = map[string]FrameType{ "earth": Earth, "kitty": Kitty, "india": India, + "brittany": Brittany, } From 2f6691fab5a7f2690a58f2322979c33744910b86 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Thu, 20 Mar 2025 16:22:21 +0100 Subject: [PATCH 03/11] adds github actions workflow --- .github/workflows/.github-ci.yml | 51 ++++++++++++++++++++++++++++++++ .github/workflows/main.yml | 22 -------------- 2 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/.github-ci.yml delete mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/.github-ci.yml b/.github/workflows/.github-ci.yml new file mode 100644 index 0000000..1d686fd --- /dev/null +++ b/.github/workflows/.github-ci.yml @@ -0,0 +1,51 @@ +name: ci + +on: push + +jobs: + build: + runs-on: ubuntu-22.04 + + steps: + - + name: Repository meta + id: repository + run: | + registry=${{ github.server_url }} + registry=${registry##http*://} + echo "registry=${registry}" >> "$GITHUB_OUTPUT" + echo "registry=${registry}" + repository="$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')" + echo "repository=${repository}" >> "$GITHUB_OUTPUT" + echo "repository=${repository}" + - + name: Docker meta + uses: docker/metadata-action@v5 + id: docker + with: + images: ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }} + - + name: Login to registry + uses: docker/login-action@v3 + with: + registry: ${{ steps.repository.outputs.registry }} + username: ${{ secrets.PACKAGES_USER }} + password: ${{ secrets.PACKAGES_TOKEN }} + - + name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + buildkitd-flags: '--allow-insecure-entitlement network.host' + driver-opts: network=host + - + name: Build and push + uses: docker/build-push-action@v6 + with: + push: true + allow: network.host + network: host + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.docker.outputs.tags }} \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 5814ce3..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Docker Image CI - -on: [push] - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag hugomd/ascii-live:${GITHUB_SHA:0:8} --tag hugomd/ascii-live:latest - - name: Push docker image - env: - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} - run: | - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD - docker push hugomd/ascii-live:${GITHUB_SHA:0:8} - docker push hugomd/ascii-live:latest From 5d645947550ac2931a18a85a1b3bfc77e3523cc3 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Thu, 20 Mar 2025 17:52:12 +0000 Subject: [PATCH 04/11] working-deployment-on-kind-cluster (#1) Reviewed-on: https://forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/pulls/1 Co-authored-by: franz.germann Co-committed-by: franz.germann --- .github/workflows/.github-ci.yml | 23 +++++++++---------- .../{deployment.yml => deployment.yaml} | 8 +++---- main.go | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) rename deployment/{deployment.yml => deployment.yaml} (84%) diff --git a/.github/workflows/.github-ci.yml b/.github/workflows/.github-ci.yml index 1d686fd..d7705da 100644 --- a/.github/workflows/.github-ci.yml +++ b/.github/workflows/.github-ci.yml @@ -7,8 +7,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - - name: Repository meta + - name: Repository meta id: repository run: | registry=${{ github.server_url }} @@ -18,30 +17,30 @@ jobs: repository="$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')" echo "repository=${repository}" >> "$GITHUB_OUTPUT" echo "repository=${repository}" - - - name: Docker meta + + - name: Docker meta uses: docker/metadata-action@v5 id: docker with: images: ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }} - - - name: Login to registry + + - name: Login to registry uses: docker/login-action@v3 with: registry: ${{ steps.repository.outputs.registry }} username: ${{ secrets.PACKAGES_USER }} password: ${{ secrets.PACKAGES_TOKEN }} - - - name: Set up QEMU + + - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx + + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: buildkitd-flags: '--allow-insecure-entitlement network.host' driver-opts: network=host - - - name: Build and push + + - name: Build and push uses: docker/build-push-action@v6 with: push: true diff --git a/deployment/deployment.yml b/deployment/deployment.yaml similarity index 84% rename from deployment/deployment.yml rename to deployment/deployment.yaml index 7d3e2d5..c1037eb 100644 --- a/deployment/deployment.yml +++ b/deployment/deployment.yaml @@ -13,7 +13,7 @@ spec: app: ascii-live spec: containers: - - image: hugomd/ascii-live:407342dc + - image: forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/franz.germann/ascii-live:development name: ascii-live ports: - containerPort: 8080 @@ -44,10 +44,10 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: rules: - - host: ascii.live + - host: 192-168-197-2.traefik.me http: paths: - - path: / + - path: /ascii-live pathType: Prefix backend: service: @@ -57,4 +57,4 @@ spec: tls: - secretName: ascii-live-tls-prod-cert hosts: - - ascii.live + - 192-168-197-2.traefik.me diff --git a/main.go b/main.go index 8c91468..457d226 100644 --- a/main.go +++ b/main.go @@ -110,8 +110,8 @@ func main() { flag.Set("logtostderr", "true") r := mux.NewRouter() - r.HandleFunc("/list", listHandler).Methods("GET") - r.HandleFunc("/{frameSource}", handler).Methods("GET") + r.HandleFunc("/ascii-live/list", listHandler).Methods("GET") + r.HandleFunc("/ascii-live/{frameSource}", handler).Methods("GET") r.NotFoundHandler = http.HandlerFunc(notFoundHandler) srv := &http.Server{ From b5f063381e246288f9a4dbd6f3ba10f28349686b Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Wed, 26 Mar 2025 16:46:29 +0000 Subject: [PATCH 05/11] updates project to go1.24.1 (#2) Reviewed-on: https://forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/pulls/2 Co-authored-by: franz.germann Co-committed-by: franz.germann --- .github/workflows/.github-ci.yml | 2 +- Dockerfile | 4 ++-- go.mod | 6 +++--- go.sum | 10 ++++++---- main.go | 6 +++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/.github-ci.yml b/.github/workflows/.github-ci.yml index d7705da..acf60a0 100644 --- a/.github/workflows/.github-ci.yml +++ b/.github/workflows/.github-ci.yml @@ -46,5 +46,5 @@ jobs: push: true allow: network.host network: host - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 tags: ${{ steps.docker.outputs.tags }} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c606e1c..4a55e65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,11 @@ -FROM golang:1.17-alpine AS build-env +FROM golang:1.24.1-alpine AS build-env ENV GO111MODULE=on WORKDIR /go/src/github.com/hugomd/ascii-live/ RUN apk add ca-certificates COPY . /go/src/github.com/hugomd/ascii-live/ RUN cd /go/src/github.com/hugomd/ascii-live && \ go mod download && \ - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . + CGO_ENABLED=0 GOOS=linux go build -installsuffix cgo -o main . FROM scratch COPY --from=build-env /go/src/github.com/hugomd/ascii-live/main / diff --git a/go.mod b/go.mod index a626244..1751516 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/hugomd/ascii-live -go 1.17 +go 1.24.1 require ( - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/gorilla/mux v1.7.3 + github.com/golang/glog v1.2.4 + github.com/gorilla/mux v1.8.1 ) diff --git a/go.sum b/go.sum index 68db0f5..e5c898b 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= +github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= diff --git a/main.go b/main.go index 457d226..ff76b46 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,7 @@ import ( ) var NotFoundMessage = map[string]string{ - "error": "Frames not found. Navigate to /list for list of frames. Navigate to https://github.com/hugomd/ascii-live to submit new frames.", + "error": "Frames not found. Navigate to /ascii/list for list of frames. Navigate to https://github.com/hugomd/ascii-live to submit new frames.", } var NotCurledMessage = map[string]string{ @@ -53,7 +53,7 @@ func notCurledHandler(w http.ResponseWriter, r *http.Request) { } func handler(w http.ResponseWriter, r *http.Request) { - cn := w.(http.CloseNotifier) + ctx := r.Context() flusher := w.(http.Flusher) vars := mux.Vars(r) @@ -79,7 +79,7 @@ func handler(w http.ResponseWriter, r *http.Request) { for { select { // Handle client disconnects - case <-cn.CloseNotify(): + case <-ctx.Done(): glog.Infof("Client stopped listening") return default: From 3517d64da805ff1d69a11c6fbb077e76f3ed04dd Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Thu, 27 Mar 2025 12:45:43 +0000 Subject: [PATCH 06/11] adapt-project-structure (#3) Reviewed-on: https://forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/pulls/3 Co-authored-by: franz.germann Co-committed-by: franz.germann --- go.mod | 2 +- handlers/handlers.go | 102 +++++++++++++++++++++++++++++++++++++++++++ main.go | 101 ++---------------------------------------- 3 files changed, 107 insertions(+), 98 deletions(-) create mode 100644 handlers/handlers.go diff --git a/go.mod b/go.mod index 1751516..bc5ce83 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/hugomd/ascii-live +module forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live go 1.24.1 diff --git a/handlers/handlers.go b/handlers/handlers.go new file mode 100644 index 0000000..ea0364f --- /dev/null +++ b/handlers/handlers.go @@ -0,0 +1,102 @@ +package handlers + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/frames" + "github.com/golang/glog" + "github.com/gorilla/mux" +) + +var NotFoundMessage = map[string]string{ + "error": "Frames not found. Navigate to /ascii/list for list of frames. Navigate to https://github.com/hugomd/ascii-live to submit new frames.", +} + +var NotCurledMessage = map[string]string{ + "error": "You almost ruined a good surprise. Come on, curl it in terminal.", +} + +var availableFrames []string + +func init() { + for k := range frames.FrameMap { + availableFrames = append(availableFrames, k) + } +} + +func writeJson(w http.ResponseWriter, r *http.Request, res interface{}, status int) { + w.Header().Set("Content-Type", "application/json") + data, err := json.Marshal(res) + if err != nil { + return + } + w.WriteHeader(status) + fmt.Fprint(w, string(data)) +} + +func ListHandler(w http.ResponseWriter, r *http.Request) { + writeJson(w, r, map[string][]string{"frames": availableFrames}, http.StatusOK) +} + +func NotFoundHandler(w http.ResponseWriter, r *http.Request) { + writeJson(w, r, NotFoundMessage, http.StatusNotFound) +} + +func NotCurledHandler(w http.ResponseWriter, r *http.Request) { + writeJson(w, r, NotCurledMessage, http.StatusExpectationFailed) +} + +func Handler(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + flusher := w.(http.Flusher) + + vars := mux.Vars(r) + frameSource := vars["frameSource"] + glog.Infof("Frame source %s", frameSource) + + frames, ok := frames.FrameMap[frameSource] + if !ok { + NotFoundHandler(w, r) + return + } + + userAgent := r.Header.Get("User-Agent") + if !strings.Contains(userAgent, "curl") { + NotCurledHandler(w, r) + return + } + + w.Header().Set("Transfer-Encoding", "chunked") + w.WriteHeader(http.StatusOK) + + i := 0 + for { + select { + // Handle client disconnects + case <-ctx.Done(): + glog.Infof("Client stopped listening") + return + default: + if i >= frames.GetLength() { + i = 0 + } + // Artificially wait between reponses. + time.Sleep(frames.GetSleep()) + + // Clear screen + clearScreen := "\033[2J\033[H" + newLine := "\n" + + // Write frames + fmt.Fprint(w, clearScreen+frames.GetFrame(i)+newLine) + i++ + + // Send some data. + flusher.Flush() + } + } +} diff --git a/main.go b/main.go index ff76b46..4d75192 100644 --- a/main.go +++ b/main.go @@ -1,108 +1,15 @@ package main import ( - "encoding/json" "flag" - "fmt" "net/http" - "strings" - "time" - "github.com/hugomd/ascii-live/frames" + "forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/handlers" "github.com/golang/glog" "github.com/gorilla/mux" ) -var NotFoundMessage = map[string]string{ - "error": "Frames not found. Navigate to /ascii/list for list of frames. Navigate to https://github.com/hugomd/ascii-live to submit new frames.", -} - -var NotCurledMessage = map[string]string{ - "error": "You almost ruined a good surprise. Come on, curl it in terminal.", -} - -var availableFrames []string - -func init() { - for k := range frames.FrameMap { - availableFrames = append(availableFrames, k) - } -} - -func writeJson(w http.ResponseWriter, r *http.Request, res interface{}, status int) { - w.Header().Set("Content-Type", "application/json") - data, err := json.Marshal(res) - if err != nil { - return - } - w.WriteHeader(status) - fmt.Fprint(w, string(data)) -} - -func listHandler(w http.ResponseWriter, r *http.Request) { - writeJson(w, r, map[string][]string{"frames": availableFrames}, http.StatusOK) -} - -func notFoundHandler(w http.ResponseWriter, r *http.Request) { - writeJson(w, r, NotFoundMessage, http.StatusNotFound) -} - -func notCurledHandler(w http.ResponseWriter, r *http.Request) { - writeJson(w, r, NotCurledMessage, http.StatusExpectationFailed) -} - -func handler(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - flusher := w.(http.Flusher) - - vars := mux.Vars(r) - frameSource := vars["frameSource"] - glog.Infof("Frame source %s", frameSource) - - frames, ok := frames.FrameMap[frameSource] - if !ok { - notFoundHandler(w, r) - return - } - - userAgent := r.Header.Get("User-Agent") - if !strings.Contains(userAgent, "curl") { - notCurledHandler(w, r) - return - } - - w.Header().Set("Transfer-Encoding", "chunked") - w.WriteHeader(http.StatusOK) - - i := 0 - for { - select { - // Handle client disconnects - case <-ctx.Done(): - glog.Infof("Client stopped listening") - return - default: - if i >= frames.GetLength() { - i = 0 - } - // Artificially wait between reponses. - time.Sleep(frames.GetSleep()) - - // Clear screen - clearScreen := "\033[2J\033[H" - newLine := "\n" - - // Write frames - fmt.Fprint(w, clearScreen+frames.GetFrame(i)+newLine) - i++ - - // Send some data. - flusher.Flush() - } - } -} - // Server. func main() { flag.Parse() @@ -110,9 +17,9 @@ func main() { flag.Set("logtostderr", "true") r := mux.NewRouter() - r.HandleFunc("/ascii-live/list", listHandler).Methods("GET") - r.HandleFunc("/ascii-live/{frameSource}", handler).Methods("GET") - r.NotFoundHandler = http.HandlerFunc(notFoundHandler) + r.HandleFunc("/ascii-live/list", handlers.ListHandler).Methods("GET") + r.HandleFunc("/ascii-live/{frameSource}", handlers.Handler).Methods("GET") + r.NotFoundHandler = http.HandlerFunc(handlers.NotFoundHandler) srv := &http.Server{ Handler: r, From 6b779b17219fc5b52862031a9e51e3c7eb4e8609 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Thu, 3 Apr 2025 12:40:41 +0000 Subject: [PATCH 07/11] adds unit tests (#5) Reviewed-on: https://forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/pulls/5 Co-authored-by: franz.germann Co-committed-by: franz.germann --- go.mod | 9 ++++- go.sum | 10 +++++ handlers/handlers.go | 3 +- main.go | 2 +- tests/handlers_test.go | 69 ++++++++++++++++++++++++++++++++++ tests/handlers_testify_test.go | 66 ++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 tests/handlers_test.go create mode 100644 tests/handlers_testify_test.go diff --git a/go.mod b/go.mod index bc5ce83..107bdef 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,15 @@ -module forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live +module ascii-live go 1.24.1 require ( github.com/golang/glog v1.2.4 github.com/gorilla/mux v1.8.1 + github.com/stretchr/testify v1.10.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e5c898b..0659769 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc= github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/handlers/handlers.go b/handlers/handlers.go index ea0364f..2368fa8 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -7,7 +7,8 @@ import ( "strings" "time" - "forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/frames" + "ascii-live/frames" + "github.com/golang/glog" "github.com/gorilla/mux" ) diff --git a/main.go b/main.go index 4d75192..90c71fd 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,7 @@ import ( "flag" "net/http" - "forgejo.edf-bootstrap.cx.fg1.ffm.osc.live/Franz.Germann/ascii-live/handlers" + "ascii-live/handlers" "github.com/golang/glog" "github.com/gorilla/mux" diff --git a/tests/handlers_test.go b/tests/handlers_test.go new file mode 100644 index 0000000..cc9cebf --- /dev/null +++ b/tests/handlers_test.go @@ -0,0 +1,69 @@ +package test + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "ascii-live/handlers" + + "github.com/gorilla/mux" +) + +func TestListHandler(t *testing.T) { + r := mux.NewRouter() + r.HandleFunc("/ascii-live/list", handlers.ListHandler) + + req, err := http.NewRequest("GET", "/ascii-live/list", nil) + if err != nil { + t.Fatal(err) + } + + recorder := httptest.NewRecorder() + r.ServeHTTP(recorder, req) + + if status := recorder.Code; status != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK) + } + + var response map[string][]string + if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil { + t.Errorf("error decoding response: %v", err) + } +} + +func TestNotFoundHandler(t *testing.T) { + r := mux.NewRouter() + r.NotFoundHandler = http.HandlerFunc(handlers.NotFoundHandler) + + req, err := http.NewRequest("GET", "/not-existing", nil) + if err != nil { + t.Fatal(err) + } + + recorder := httptest.NewRecorder() + r.ServeHTTP(recorder, req) // Router verarbeitet die Anfrage + + if status := recorder.Code; status != http.StatusNotFound { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusNotFound) + } +} + +func TestNotCurledHandler(t *testing.T) { + r := mux.NewRouter() + r.HandleFunc("/ascii-live/donut", handlers.NotCurledHandler) + + req, err := http.NewRequest("GET", "/ascii-live/donut", nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36") + + recorder := httptest.NewRecorder() + r.ServeHTTP(recorder, req) + + if status := recorder.Code; status != http.StatusExpectationFailed { + t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusExpectationFailed) + } +} diff --git a/tests/handlers_testify_test.go b/tests/handlers_testify_test.go new file mode 100644 index 0000000..ad81f72 --- /dev/null +++ b/tests/handlers_testify_test.go @@ -0,0 +1,66 @@ +package test + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "ascii-live/handlers" +) + +func TestListHandler2(t *testing.T) { + req, err := http.NewRequest("GET", "/ascii/list", nil) + require.NoError(t, err, "Failed to create request") + + recorder := httptest.NewRecorder() + handler := http.HandlerFunc(handlers.ListHandler) + + handler.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusOK, recorder.Code, "Status code should be OK") + assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"), "Content-Type should be application/json") + + var responseBody map[string][]string + err = json.Unmarshal(recorder.Body.Bytes(), &responseBody) + require.NoError(t, err, "Failed to unmarshal response JSON") + +} + +func TestNotFoundHandler2(t *testing.T) { + req, err := http.NewRequest("GET", "/some/unknown/path", nil) + require.NoError(t, err, "Failed to create request") + + recorder := httptest.NewRecorder() + handler := http.HandlerFunc(handlers.NotFoundHandler) // Test directly + + expectedBodyBytes, err := json.Marshal(handlers.NotFoundMessage) + require.NoError(t, err, "Failed to marshal expected NotFoundMessage") + + handler.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusNotFound, recorder.Code, "Status code should be Not Found") + assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"), "Content-Type should be application/json") + assert.JSONEq(t, string(expectedBodyBytes), recorder.Body.String(), "Response body does not match expected NotFoundMessage") +} + +func TestNotCurledHandler2(t *testing.T) { + req, err := http.NewRequest("GET", "/ascii/someframe", nil) + require.NoError(t, err, "Failed to create request") + // crucially, DO NOT set User-Agent to 'curl' + + recorder := httptest.NewRecorder() + handler := http.HandlerFunc(handlers.NotCurledHandler) // Test directly + + expectedBodyBytes, err := json.Marshal(handlers.NotCurledMessage) + require.NoError(t, err, "Failed to marshal expected NotCurledMessage") + + handler.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusExpectationFailed, recorder.Code, "Status code should be Expectation Failed") + assert.Equal(t, "application/json", recorder.Header().Get("Content-Type"), "Content-Type should be application/json") + assert.JSONEq(t, string(expectedBodyBytes), recorder.Body.String(), "Response body does not match expected NotCurledMessage") +} From 0ac58cfdbbae893fba52f0895788ac37079d4627 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Mon, 28 Apr 2025 14:05:38 +0200 Subject: [PATCH 08/11] updates host in deployment.yaml --- deployment/deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/deployment.yaml b/deployment/deployment.yaml index c1037eb..339d111 100644 --- a/deployment/deployment.yaml +++ b/deployment/deployment.yaml @@ -44,7 +44,7 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: rules: - - host: 192-168-197-2.traefik.me + - host: https://factory.c-one-infra.de http: paths: - path: /ascii-live @@ -57,4 +57,4 @@ spec: tls: - secretName: ascii-live-tls-prod-cert hosts: - - 192-168-197-2.traefik.me + - https://factory.c-one-infra.de From bd09827c56ba7e32f14e7cec9e3da3ac40c55029 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Mon, 28 Apr 2025 14:07:50 +0200 Subject: [PATCH 09/11] updates host in deployment.yaml --- deployment/deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment/deployment.yaml b/deployment/deployment.yaml index 339d111..55e485e 100644 --- a/deployment/deployment.yaml +++ b/deployment/deployment.yaml @@ -44,7 +44,7 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "false" spec: rules: - - host: https://factory.c-one-infra.de + - host: factory.c-one-infra.de http: paths: - path: /ascii-live @@ -57,4 +57,4 @@ spec: tls: - secretName: ascii-live-tls-prod-cert hosts: - - https://factory.c-one-infra.de + - factory.c-one-infra.de From 3717327e7f73c270f2ddaa0cf36f933c4ec78dfe Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Mon, 28 Apr 2025 14:34:46 +0200 Subject: [PATCH 10/11] testing local build --- .github/workflows/.github-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/.github-ci.yml b/.github/workflows/.github-ci.yml index acf60a0..2000290 100644 --- a/.github/workflows/.github-ci.yml +++ b/.github/workflows/.github-ci.yml @@ -5,7 +5,6 @@ on: push jobs: build: runs-on: ubuntu-22.04 - steps: - name: Repository meta id: repository From e72ef905ce5508e96d49455bc2013ee62adfbd95 Mon Sep 17 00:00:00 2001 From: "franz.germann" Date: Mon, 28 Apr 2025 15:38:54 +0200 Subject: [PATCH 11/11] testing removal of ca-certicates from docker file --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4a55e65..692a233 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM golang:1.24.1-alpine AS build-env ENV GO111MODULE=on WORKDIR /go/src/github.com/hugomd/ascii-live/ -RUN apk add ca-certificates +# RUN apk add ca-certificates COPY . /go/src/github.com/hugomd/ascii-live/ RUN cd /go/src/github.com/hugomd/ascii-live && \ go mod download && \ @@ -9,5 +9,5 @@ RUN cd /go/src/github.com/hugomd/ascii-live && \ FROM scratch COPY --from=build-env /go/src/github.com/hugomd/ascii-live/main / -COPY --from=build-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +# COPY --from=build-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt CMD ["/main"]