added structure for db

This commit is contained in:
Radu Macocian (admac)
2026-06-12 16:44:04 +02:00
parent de546d8df4
commit 4f989aa512
8 changed files with 252 additions and 58 deletions
+19
View File
@@ -14,6 +14,25 @@ type Config struct {
Api ApiConfig
Llm LLMConfig
Logging []LogConfig
Db DbConfig
}
type DbConfig struct {
Url string
Port string
DbName string
User string
Password string
History HistoryConfig
Memory MemoryConfig
}
type MemoryConfig struct {
Enabled bool
}
type HistoryConfig struct {
Enabled bool
}
type ApiConfig struct {
+65
View File
@@ -0,0 +1,65 @@
package history
import (
"net"
"net/url"
"git.estatecloud.org/radumaco/souvenir/config"
"git.estatecloud.org/radumaco/souvenir/model"
"github.com/gopsql/pgx"
)
type DbClient struct {
Cfg config.DbConfig
}
type Conversation struct {
Id string
Messages []model.Message
}
func (client DbClient) init() error {
const createConversationTable = `
CREATE TABLE IF NOT EXISTS conversations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
)`
const createMessageTable = `
CREATE TABLE IF NOT EXISTS messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
role TEXT NOT NULL
content TEXT NOT NULL
conversation_id UUID
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
)`
const createToolCallTable = `
CREATE TABLE IF NOT EXISTS tool_calls (
id UUID PRIMARY KEY,
type TEXT NOT NULL
functionName TEXT NOT NULL
functionArgs TEXT NOT NULL
message_id UUID
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
)`
conn := pgx.MustOpen(client.connectionString())
defer conn.Close()
if _, err := conn.Exec(createToolCallTable); err != nil {
return err
}
if _, err := conn.Exec(createToolCallTable); err != nil {
return err
}
return nil
}
func (client DbClient) connectionString() string {
u := &url.URL{
Scheme: "postgres",
User: url.UserPassword(client.Cfg.User, client.Cfg.Password),
Host: net.JoinHostPort(client.Cfg.Url, client.Cfg.Port),
Path: client.Cfg.DbName,
}
return u.String()
}
+11
View File
@@ -8,6 +8,16 @@ require (
charm.land/lipgloss/v2 v2.0.3
)
require (
github.com/gopsql/db v1.2.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/text v0.9.0 // indirect
)
require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect
@@ -18,6 +28,7 @@ require (
github.com/charmbracelet/x/windows v0.2.2 // indirect
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/gopsql/pgx v1.5.0
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
github.com/mattn/go-runewidth v0.0.23 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
+74
View File
@@ -28,19 +28,93 @@ github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSE
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gopsql/db v1.2.1 h1:dzi13FK9OCeV2pARpmn4kSp351Uzg/Le2mEKo43H+EQ=
github.com/gopsql/db v1.2.1/go.mod h1:plazrQDxoOfbv749q6AqZyR0wtPak19s4uw8J8pnMYA=
github.com/gopsql/pgx v1.5.0 h1:0kuDwjS2lCFTWUe8w0mBXM6JCTGKCwtPg3zEtDH0Lpw=
github.com/gopsql/pgx v1.5.0/go.mod h1:F95IVkBjVotZIiN8UtSdZBe111alDqRaOERaLQeY9pg=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+17 -32
View File
@@ -10,6 +10,7 @@ import (
"strconv"
config "git.estatecloud.org/radumaco/souvenir/config"
"git.estatecloud.org/radumaco/souvenir/model"
)
type LLMClient struct {
@@ -19,15 +20,9 @@ type LLMClient struct {
// Request Types
type ChatRequest struct {
Model string `json:"model"`
Messages []Message `json:"messages"`
Tools []config.Tool `json:"tools,omitempty"`
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
Model string `json:"model"`
Messages []model.Message `json:"messages"`
Tools []config.Tool `json:"tools,omitempty"`
}
// Response types //
@@ -42,20 +37,9 @@ type ChatResponse struct {
}
type Choice struct {
Index int `json:"index"`
Message Message `json:"message"`
FinishReason string `json:"finish_reason"`
}
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type"`
Function ToolCallFunc `json:"function"`
}
type ToolCallFunc struct {
Name string `json:"name"`
Arguments string `json:"arguments"`
Index int `json:"index"`
Message model.Message `json:"message"`
FinishReason string `json:"finish_reason"`
}
type Usage struct {
@@ -64,7 +48,8 @@ type Usage struct {
TotalTokens int `json:"total_tokens"`
}
func (client LLMClient) Call(query string, messages []Message) ([]Message, error) {
func (client LLMClient) Call(query string, messages []model.Message) ([]model.Message, error) {
return []model.Message{{Role: "assistant", Content: "message 1"}, {Role: "assistant", Content: "message 2"}}, nil
var logger = slog.Default().With("Component", "LLM Client")
requestBody := ChatRequest{
Model: client.Cfg.Llm.Model,
@@ -73,7 +58,7 @@ func (client LLMClient) Call(query string, messages []Message) ([]Message, error
}
serialized, err := json.Marshal(requestBody)
if err != nil {
return []Message{}, err
return []model.Message{}, err
}
body := bytes.NewBuffer(serialized)
@@ -81,14 +66,14 @@ func (client LLMClient) Call(query string, messages []Message) ([]Message, error
req, err := http.NewRequest("POST", client.Cfg.Api.Url, body)
if err != nil {
logger.Error("There was an error creating the request", "error", err.Error())
return []Message{}, err
return []model.Message{}, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+client.Cfg.Api.Key)
resp, err := http.DefaultClient.Do(req)
if err != nil {
logger.Error("There was an error during http call", "error", err.Error())
return []Message{}, err
return []model.Message{}, err
}
logger.Debug("LLM Call returned", "response", resp)
defer resp.Body.Close()
@@ -96,13 +81,13 @@ func (client LLMClient) Call(query string, messages []Message) ([]Message, error
data, err := io.ReadAll(resp.Body)
if err != nil {
logger.Error("There was an error reading the response body", "error", err.Error())
return []Message{}, err
return []model.Message{}, err
}
if resp.StatusCode != 200 && resp.StatusCode != 202 {
logger.Error("Call returned non 200 status",
"statusCode", resp.StatusCode,
"status", resp.Status)
return []Message{},
return []model.Message{},
errors.New("Call returned invalid status " +
strconv.Itoa(resp.StatusCode) +
resp.Status)
@@ -112,13 +97,13 @@ func (client LLMClient) Call(query string, messages []Message) ([]Message, error
var response ChatResponse
if err := json.Unmarshal(data, &response); err != nil {
logger.Error("There was an error parsing the response", "error", err.Error())
return []Message{}, err
return []model.Message{}, err
}
var result []Message
var result []model.Message
if len(response.Choices) == 0 {
logger.Error("The call returned an empty response")
return []Message{}, errors.New("The call returned an empty response")
return []model.Message{}, errors.New("The call returned an empty response")
}
for _, choice := range response.Choices {
logger.Error("Appending response message", "message", choice.Message)
+14
View File
@@ -0,0 +1,14 @@
package model
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
}
type ToolCall struct {
ID string `json:"id"`
Type string `json:"type"`
FunctionName string `json:"function"`
FunctionArguments string `json:"arguments"`
}
+23 -15
View File
@@ -12,13 +12,14 @@ import (
"charm.land/lipgloss/v2"
"git.estatecloud.org/radumaco/souvenir/config"
llm "git.estatecloud.org/radumaco/souvenir/llm"
"git.estatecloud.org/radumaco/souvenir/model"
)
var logger *slog.Logger
type model struct {
type uiModel struct {
viewport viewport.Model
messages []llm.Message
messages []model.Message
textarea textarea.Model
senderStyle lipgloss.Style
agentStyle lipgloss.Style
@@ -31,11 +32,11 @@ type model struct {
}
type agentResponseMessage struct {
response []llm.Message
response []model.Message
err error
}
func InitialModel(config config.Config) model {
func InitialModel(config config.Config) uiModel {
logger = slog.Default().With("Component", "UI")
ta := textarea.New()
ta.Placeholder = "Send a message..."
@@ -61,9 +62,9 @@ func InitialModel(config config.Config) model {
ta.KeyMap.InsertNewline.SetEnabled(false)
return model{
return uiModel{
textarea: ta,
messages: []llm.Message{},
messages: []model.Message{},
viewport: vp,
senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")),
errorStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("9")),
@@ -73,17 +74,17 @@ func InitialModel(config config.Config) model {
}
}
func (m model) Init() tea.Cmd {
func (m uiModel) Init() tea.Cmd {
return textarea.Blink
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
logger.Debug("Received WindowSizeMsg", "width", msg.Width, "height", msg.Height)
m.viewport.SetWidth(msg.Width * 80 / 100)
m.textarea.SetWidth(msg.Width * 80 / 100)
m.viewport.SetHeight(msg.Height - m.textarea.Height())
m.viewport.SetHeight(msg.Height - lipgloss.Height(m.textarea.View()))
m.width = msg.Width
m.height = msg.Height
@@ -94,18 +95,24 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} else {
m.viewport.SetContent(renderLanding(m.viewport.Width(), m.viewport.Height()))
}
logger.Debug("New sizes",
"vp width", m.viewport.Width(), "vp height", m.viewport.Height(),
"ta width", m.textarea.Width(), "ta height", m.textarea.Height())
m.viewport.GotoBottom()
case tea.KeyPressMsg:
logger.Debug("Received KeyPressMsg")
logger.Debug("Received KeyPressMsg", "msg", msg)
switch msg.String() {
case "ctrl+c", "esc":
logger.Debug("Received exit sequence. Quiting")
fmt.Println(m.textarea.Value())
return m, tea.Quit
case "shift+enter", "ctrl+j", "alt+enter":
m.textarea.InsertRune('\n')
return m, nil
case "enter":
input := m.textarea.Value()
m.messages = append(m.messages, llm.Message{
m.messages = append(m.messages, model.Message{
Content: input,
Role: "user",
})
@@ -134,7 +141,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
resp := msg.response
if msg.err != nil {
logger.Error("Message is error", "error", msg.err)
resp = []llm.Message{{
resp = []model.Message{{
Role: "Error",
Content: msg.err.Error(),
}}
@@ -146,13 +153,14 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
var messages = m.renderMessages()
m.viewport.SetContent(lipgloss.NewStyle().Width(m.viewport.Width()).Render(messages))
m.viewport.GotoBottom()
return m, nil
}
return m, nil
}
func (m model) View() tea.View {
func (m uiModel) View() tea.View {
ui := lipgloss.JoinVertical(
lipgloss.Left,
m.viewport.View(),
@@ -169,7 +177,7 @@ func (m model) View() tea.View {
return view
}
func (m model) callAgent(input string, messages []llm.Message) tea.Cmd {
func (m uiModel) callAgent(input string, messages []model.Message) tea.Cmd {
logger.Debug("Calling agent", "query", input, "messages", messages)
return func() tea.Msg {
resp, err := m.client.Call(input, messages)
@@ -177,7 +185,7 @@ func (m model) callAgent(input string, messages []llm.Message) tea.Cmd {
}
}
func (m model) renderMessages() string {
func (m uiModel) renderMessages() string {
var result strings.Builder
var width = m.viewport.Width()
for _, message := range m.messages {
+29 -11
View File
@@ -2,17 +2,35 @@ package ui
import "charm.land/lipgloss/v2"
// Logo is the souvenir snow-globe banner (ANSI 256-color, half-block).
const Logo = "\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;111m▄\x1b[0m\x1b[38;5;111m▄\x1b[38;5;111;48;5;152m▀\x1b[38;5;111;48;5;152m▀\x1b[38;5;111;48;5;152m▀\x1b[38;5;111;48;5;152m▀\x1b[0m\x1b[38;5;111m▄\x1b[0m\x1b[38;5;111m▄\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m\x1b[38;5;111m▄\x1b[38;5;111;48;5;111m▀\x1b[38;5;111;48;5;152m▀\x1b[38;5;152;48;5;195m▀\x1b[38;5;152;48;5;231m▀\x1b[38;5;152;48;5;195m▀\x1b[38;5;195;48;5;195m▀\x1b[38;5;195;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;111;48;5;152m▀\x1b[38;5;111;48;5;111m▀\x1b[0m\x1b[38;5;111m▄\x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m\x1b[38;5;111m▄\x1b[38;5;111;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;195;48;5;195m▀\x1b[38;5;195;48;5;231m▀\x1b[38;5;195;48;5;195m▀\x1b[38;5;195;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;231;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;111;48;5;152m▀\x1b[0m\x1b[38;5;111m▄\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[38;5;111;48;5;111m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;195;48;5;195m▀\x1b[38;5;195;48;5;195m▀\x1b[38;5;195;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;28m▀\x1b[38;5;152;48;5;22m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;231;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;111;48;5;111m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;195;48;5;152m▀\x1b[38;5;152;48;5;231m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;22;48;5;22m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;231;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[38;5;111;48;5;111m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;28;48;5;28m▀\x1b[38;5;22;48;5;22m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;152;48;5;152m▀\x1b[38;5;111;48;5;111m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m\x1b[38;5;111m▀\x1b[38;5;231;48;5;111m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;94;48;5;231m▀\x1b[38;5;94;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;111m▀\x1b[0m\x1b[38;5;111m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;130m\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[38;5;214;48;5;130m▀\x1b[0m\x1b[38;5;130m\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;130m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[38;5;130;48;5;94m▀\x1b[0m\x1b[38;5;130m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n"
// Logo is the synthwave sunset postcard (tilted, ANSI 256-color, half-block).
const Logo = "\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[0m\x1b[38;5;231m▄\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;252m▀\x1b[38;5;231;48;5;252m▀\x1b[38;5;231;48;5;252m▀\x1b[38;5;231;48;5;252m▀\x1b[38;5;231;48;5;252m▀\x1b[38;5;231;48;5;125m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;16m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;231;48;5;125m▀\x1b[38;5;125;48;5;252m▀\x1b[38;5;252;48;5;252m▀\x1b[38;5;252;48;5;16m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;252;48;5;90m▀\x1b[38;5;252;48;5;125m▀\x1b[38;5;252;48;5;252m▀\x1b[38;5;231;48;5;125m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;16;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;90m\x1b[38;5;231;48;5;90m\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;231;48;5;90m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;90m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;125;48;5;231m▀\x1b[38;5;252;48;5;125m▀\x1b[38;5;16;48;5;252m▀\x1b[38;5;231;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;231;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;231;48;5;16m▀\x1b[38;5;16;48;5;125m▀\x1b[38;5;252;48;5;161m▀\x1b[38;5;125;48;5;252m▀\x1b[38;5;231;48;5;161m▀\x1b[38;5;125;48;5;231m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;231;48;5;197m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;90m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;90;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;252;48;5;252m▀\x1b[38;5;161;48;5;252m▀\x1b[38;5;231;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;231;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;231;48;5;161m▀\x1b[38;5;252;48;5;252m▀\x1b[38;5;252;48;5;197m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;125m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;231m▀\x1b[38;5;161;48;5;231m▀\x1b[38;5;161;48;5;231m▀\x1b[38;5;16;48;5;231m▀\x1b[38;5;161;48;5;16m▀\x1b[38;5;16;48;5;231m▀\x1b[38;5;161;48;5;231m▀\x1b[38;5;231;48;5;197m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;197;48;5;231m▀\x1b[38;5;252;48;5;202m▀\x1b[38;5;252;48;5;197m▀\x1b[38;5;197;48;5;252m▀\x1b[38;5;197;48;5;252m▀\x1b[38;5;197;48;5;252m▀\x1b[38;5;252;48;5;252m▀\x1b[38;5;202;48;5;231m▀\x1b[38;5;231;48;5;208m▀\x1b[38;5;231;48;5;202m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;202;48;5;231m▀\x1b[38;5;197;48;5;231m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;197;48;5;208m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;231;48;5;202m▀\x1b[38;5;231;48;5;208m▀\x1b[38;5;231;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;125;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;161m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;231;48;5;229m▀\x1b[38;5;231;48;5;208m▀\x1b[38;5;208;48;5;231m▀\x1b[38;5;202;48;5;231m▀\x1b[38;5;208;48;5;231m▀\x1b[38;5;202;48;5;231m▀\x1b[38;5;208;48;5;231m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;214m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;214m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;214m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;214m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;161;48;5;197m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;197m▀\x1b[38;5;197;48;5;202m▀\x1b[38;5;197;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;197;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;197;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;197;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;208;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;229m▀\x1b[38;5;229;48;5;227m▀\x1b[38;5;229;48;5;227m▀\x1b[38;5;208;48;5;227m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;231;48;5;54m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;208;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;16m▀\x1b[38;5;202;48;5;16m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;208;48;5;208m▀\x1b[38;5;202;48;5;202m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;16m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;202;48;5;208m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;214;48;5;208m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;208;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;229;48;5;54m▀\x1b[38;5;229;48;5;54m▀\x1b[38;5;227;48;5;54m▀\x1b[38;5;227;48;5;54m▀\x1b[38;5;227;48;5;54m▀\x1b[38;5;227;48;5;227m▀\x1b[38;5;227;48;5;227m▀\x1b[38;5;227;48;5;227m▀\x1b[38;5;227;48;5;227m▀\x1b[38;5;227;48;5;227m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;208;48;5;16m▀\x1b[38;5;214;48;5;16m▀\x1b[38;5;208;48;5;54m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;208;48;5;16m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;214;48;5;16m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;16m▀\x1b[38;5;214;48;5;16m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;214;48;5;214m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;214;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;16;48;5;54m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;16m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;16;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;30;48;5;231m▀\x1b[38;5;231;48;5;31m▀\x1b[38;5;30;48;5;231m▀\x1b[38;5;231;48;5;31m▀\x1b[38;5;51;48;5;231m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;38;48;5;230m▀\x1b[38;5;38;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;38;48;5;195m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;231;48;5;222m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;54;48;5;54m▀\x1b[38;5;54;48;5;51m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;54;48;5;30m▀\x1b[38;5;16;48;5;30m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;30m▀\x1b[38;5;51;48;5;16m▀\x1b[38;5;30;48;5;30m▀\x1b[38;5;16;48;5;31m▀\x1b[38;5;51;48;5;16m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;16;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;16;48;5;31m▀\x1b[38;5;31;48;5;16m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;31;48;5;38m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;31;48;5;38m▀\x1b[38;5;226;48;5;37m▀\x1b[38;5;51;48;5;226m▀\x1b[38;5;226;48;5;37m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;37;48;5;45m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;195;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;30;48;5;51m▀\x1b[38;5;31;48;5;30m▀\x1b[38;5;30;48;5;31m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;31m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;51;48;5;31m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;31;48;5;31m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;38;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;51;48;5;195m▀\x1b[38;5;38;48;5;230m▀\x1b[38;5;38;48;5;195m▀\x1b[38;5;51;48;5;230m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;37;48;5;226m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;45m▀\x1b[38;5;38;48;5;45m▀\x1b[38;5;51;48;5;45m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;38;48;5;230m▀\x1b[38;5;51;48;5;195m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;31;48;5;51m▀\x1b[38;5;37;48;5;31m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;31;48;5;37m▀\x1b[38;5;16;48;5;31m▀\x1b[38;5;31;48;5;16m▀\x1b[38;5;37;48;5;31m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;51;48;5;37m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;195;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;195;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;51;48;5;230m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;37;48;5;51m▀\x1b[38;5;37;48;5;37m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;37;48;5;38m▀\x1b[38;5;51;48;5;38m▀\x1b[38;5;37;48;5;45m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;38;48;5;230m▀\x1b[38;5;195;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;231;48;5;179m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[0m\x1b[38;5;231m▄\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;38m▀\x1b[38;5;38;48;5;51m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;38;48;5;16m▀\x1b[38;5;51;48;5;45m▀\x1b[38;5;38;48;5;45m▀\x1b[38;5;38;48;5;45m▀\x1b[38;5;51;48;5;45m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;16;48;5;195m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;222;48;5;16m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;137;48;5;137m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;137;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;45;48;5;230m▀\x1b[38;5;45;48;5;195m▀\x1b[38;5;45;48;5;51m▀\x1b[38;5;38;48;5;45m▀\x1b[38;5;45;48;5;38m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;230;48;5;230m▀\x1b[38;5;195;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;16;48;5;222m▀\x1b[38;5;16;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;195;48;5;230m▀\x1b[38;5;230;48;5;222m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;16;48;5;16m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;222m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;179;48;5;137m▀\x1b[38;5;179;48;5;179m▀\x1b[38;5;137;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;137;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;137;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;137;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;222;48;5;179m▀\x1b[38;5;16;48;5;179m▀\x1b[38;5;16;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;179;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;231;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;17m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;17;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[38;5;231;48;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n" +
"\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m\x1b[38;5;231m▀\x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m \x1b[0m\n"
const Wordmark = `
___ ___ _ ___ _____ _ __ (_)_ __