{"id":17093674,"url":"https://github.com/herminiotorres/tetris","last_synced_at":"2025-03-23T16:42:04.936Z","repository":{"id":144762337,"uuid":"307890904","full_name":"herminiotorres/tetris","owner":"herminiotorres","description":"Tetris In LiveView videos by Groxio Learning","archived":false,"fork":false,"pushed_at":"2020-10-28T15:40:31.000Z","size":128,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-28T22:45:12.091Z","etag":null,"topics":["elixir","game","groxio","learning","liveview","phoenix","tetris"],"latest_commit_sha":null,"homepage":"http://bit.ly/GroxioTetris","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/herminiotorres.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-28T02:58:02.000Z","updated_at":"2022-07-31T15:07:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"6106fc0f-e3b0-4e2c-bc2e-6405fd7adee1","html_url":"https://github.com/herminiotorres/tetris","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herminiotorres%2Ftetris","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herminiotorres%2Ftetris/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herminiotorres%2Ftetris/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herminiotorres%2Ftetris/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/herminiotorres","download_url":"https://codeload.github.com/herminiotorres/tetris/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245136323,"owners_count":20566584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","game","groxio","learning","liveview","phoenix","tetris"],"created_at":"2024-10-14T14:07:57.323Z","updated_at":"2025-03-23T16:42:04.913Z","avatar_url":"https://github.com/herminiotorres.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tetris Phoenix LiveView\n\nTetris In LiveView videos can be found at [Groxio Learning YouTube](https://www.youtube.com/c/Groxio) - Two videos per week will be released starting __10/26/2020__ through __12/14/2020__, and you can follow theses videos on http://bit.ly/GroxioTetris.\n\nThe Tetris in Elixir is an updated live coding video series by [Bruce Tate](https://twitter.com/redrapids) using Phoenix LiveView version 1.5. This series supports the [Groxio Learning](https://grox.io/) mentoring programs at Red Bank High School, Chattanooga's Gig City Elixir, and ElixirChatt.\n\n__Join our Discord Community!__ https://discord.gg/VQnJQAu\n\nSkills include Reducers and protocols. LiveView links, events, lifecycle, and code organization.\n\nAlong the way, we’ll learn a little Elixir, some Phoenix, and also LiveView.\n\n## Table of content\n  * [01 - Introduction and Reducers](#01---introduction-and-reducers)\n  * [02 - Structs](#02---structs)\n\n## 01 - Introduction and Reducers\n\n  * [__YouTube Link__](https://www.youtube.com/watch?v=8h8tWcz115M\u0026list=PLKBMoE8mCkXi-sAkesjaUnDQqyrkAK8R5\u0026index=1)\n\n### Prerequisite\n\n  * [Elixir](https://elixir-lang.org/install.html)\n  * [Postgres](https://www.postgresql.org/download/)\n  * [Phoenix](https://hexdocs.pm/phoenix/installation.html)\n  * [Elixir - Getting Started](https://elixir-lang.org/getting-started/introduction.html)\n  * [Elixir School](https://elixirschool.com/en/)\n  * [Phoenix - Up and Running](https://hexdocs.pm/phoenix/up_and_running.html#content)\n  * [Ecto - Getting Started](https://hexdocs.pm/ecto/getting-started.html)\n\nIt create a new phoenix project include LiveView. After we guarantee our environment has Elixir, Postgres and Phoenix are all installed, we can continue and run this command:\n```shell\n $ mix phx.new\n\n                                  mix phx.new                                   \n\nCreates a new Phoenix project.\n\nIt expects the path of the project as an argument.\n\n    mix phx.new PATH [--module MODULE] [--app APP]\n\nA project at the given PATH will be created. The application name and module\nname will be retrieved from the path, unless --module or --app is given.\n\n## Options\n\n  • --live - include Phoenix.LiveView to make it easier than ever to build\n    interactive, real-time applications\n```\n\nThe Ecto package by default use a Postgres Database, so you need to install the database and guarantee your service it's running, after that you maybe change your credentials to access your database on `config/dev.exs` file. Now with a correct configuration to access our database, it could be run the `ecto.create` to create the database, but before we continue and create our database, you need to be more familiar with ecto task are available to us, so run:\n\n```shell\nmix ecto\nEcto v3.5.3\nA toolkit for data mapping and language integrated query for Elixir.\n\nAvailable tasks:\n\nmix ecto.create        # Creates the repository storage\nmix ecto.drop          # Drops the repository storage\nmix ecto.dump          # Dumps the repository database structure\nmix ecto.gen.migration # Generates a new migration for the repo\nmix ecto.gen.repo      # Generates a new repository\nmix ecto.load          # Loads previously dumped database structure\nmix ecto.migrate       # Runs the repository migrations\nmix ecto.migrations    # Displays the repository migration status\nmix ecto.reset         # Alias defined in mix.exs\nmix ecto.rollback      # Rolls back the repository migrations\nmix ecto.setup         # Alias defined in mix.exs\n```\n\nNow running the `ecto.create`:\n```shell\n$ mix ecto.create\nThe database for Tetris.Repo has been created\n```\n\nBefore jump and write some code, its very important you need to be more familiar with `IEx` is an abbreviation of \"Interactive Elixir\", and the `IEx Commands` and most `Data Types`.\n\n#### Prior Knowledge\n\n  * [Tetris Guideline](https://tetris.fandom.com/wiki/Tetris_Guideline)\n  * [Funcional Programming](https://inquisitivedeveloper.com/lwm-elixir-3/)\n  * [IEx](https://inquisitivedeveloper.com/lwm-elixir-5/)\n  * [IEx and Code Comments](https://inquisitivedeveloper.com/lwm-elixir-12/)\n  * [Data Types](https://inquisitivedeveloper.com/lwm-elixir-6/)\n  * [Modules and Functions - Part 1](https://inquisitivedeveloper.com/lwm-elixir-10/)\n  * [Modules and Functions - Part 2](https://inquisitivedeveloper.com/lwm-elixir-11/)\n  * [Tuples](https://inquisitivedeveloper.com/lwm-elixir-13/)\n  * [Introducing reducees](http://blog.plataformatec.com.br/2015/05/introducing-reducees/)\n  * [The Tuple Module](https://inquisitivedeveloper.com/lwm-elixir-26/)\n  * [The Enum Module Part 1](https://inquisitivedeveloper.com/lwm-elixir-28/)\n  * [The Enum Module Part 2](https://inquisitivedeveloper.com/lwm-elixir-31/)\n  * [The Enum Module Part 3](https://inquisitivedeveloper.com/lwm-elixir-33/)\n  * [The Enum Module Part 4](https://inquisitivedeveloper.com/lwm-elixir-36/)\n\nWe will initiate our code creating the first module, called Point.\n```shell\n$ touch lib/tetris/point.ex\n```\nThe module is a bucket for our code where we will put everything on when the code make sense and belonging of the rest of code.\n\nFor a build design of our code and module we almost have three kind of functions.\n\n  * Constructor - It will be our initialize function.\n  * Reducer - The reducer will receive as a parameter a kind of data type and will return the same kind of data type, but our reducer function will change doing transform our data and return a new data.\n\n#### IEX Session\n```elixir\n$ iex -S mix\nErlang/OTP 23 [erts-11.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]\n\nInteractive Elixir (1.11.1) - press Ctrl+C to exit (type h() ENTER for help)\niex\u003e Tetris.Point.origin()\n{0, 0}\niex\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex\u003e alias Tetris.Point\nTetris.Point\niex\u003e Point.origin()\n{0, 0}\niex\u003e point = Point.origin()\n{0, 0}\niex\u003e Point.left(point)\n{-1, 0}\niex\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex\u003e Point.origin() |\u003e Point.right()\n{1, 0}\niex\u003e point |\u003e Point.right() |\u003e Point.right() |\u003e Point.down()\n{2, 1}\niex\u003e point\n{0, 0}\niex\u003e add = fn x, y -\u003e x + y end\n#Function\u003c43.97283095/2 in :erl_eval.expr/5\u003e\niex\u003e list = [1,2,3]\n[1, 2, 3]\niex\u003e Enum.reduce(list, 0, add)\n6\niex\u003e 0 |\u003e add.(1) |\u003e add.(2) |\u003e add.(3)\n6\n```\n\n## 02 - Structs\n\n#### Prior Knowledge\n\n  * [Maps](https://inquisitivedeveloper.com/lwm-elixir-17/)\n  * [The Map Module Part 1](https://inquisitivedeveloper.com/lwm-elixir-47/)\n  * [The Map Module Part 2](https://inquisitivedeveloper.com/lwm-elixir-49/)\n  * [Structs](https://inquisitivedeveloper.com/lwm-elixir-18/)\n  * [Lists](https://inquisitivedeveloper.com/lwm-elixir-14/)\n  * [Keyword Lists](https://inquisitivedeveloper.com/lwm-elixir-19/)\n  * [Atom Part 1](https://elixir-lang.org/getting-started/basic-types.html#atoms)\n  * [Atom Part 2](https://elixirschool.com/en/lessons/basics/basics/#atoms)\n  * [Sigils](https://inquisitivedeveloper.com/lwm-elixir-41/)\n  * [The Kernel Module Part 1](https://inquisitivedeveloper.com/lwm-elixir-50/)\n  * [The Kernel Module Part 2](https://inquisitivedeveloper.com/lwm-elixir-53/)\n  * [The Kernel Module Part 3](https://inquisitivedeveloper.com/lwm-elixir-54/)\n  * [The Kernel Module Part 4](https://inquisitivedeveloper.com/lwm-elixir-62/)\n  * [The Kernel Module Part 5](https://inquisitivedeveloper.com/lwm-elixir-68/)\n  * [Default Values and Multiple Function Clauses](https://inquisitivedeveloper.com/lwm-elixir-25/)\n  * [Pattern Matching](https://inquisitivedeveloper.com/lwm-elixir-22/)\n  * [Functions and Pattern Matching](https://inquisitivedeveloper.com/lwm-elixir-23/)\n  * [Composing Functions](https://inquisitivedeveloper.com/lwm-elixir-29/)\n  * [A community driven style guide for Elixir](https://github.com/christopheradams/elixir_style_guide)\n  * [Credo - A static code analysis tool for the Elixir](https://github.com/rrrene/credo)\n\nFor the second lesson, it will develop the main module to our game, called Tetromino. It's our public API.\n\nThe module will be its only data type use struct, and a static constructor to guarantee the same data for the struct and giving another constructor to random the data.\n\nThe Tetromino, will be:\n  * ___shape___ - _:i, :j, :l, :o, :z, :s, :t_.\n  * ___rotation___ - _0 90 180 270_.\n  * ___location___ - using the cartisian plan and the module point to change the current location.\n\nAnd we will see the differences between structs and maps, and they're on particularities to interact with their data types and transform the data.\n\n___HINT:___ using the `v()` IEx Command to access some particular return in the IEx history lines of execution.\n\nThe Tetromino will have they on reducers functions to change the data and if it is necessary using as like a `factory process`: input -\u003e transformations -\u003e output, and pass to the next step doing your computations in the data.\n\n#### IEX Session\n```elixir\n$ iex -S mix\nErlang/OTP 23 [erts-11.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]\n\nInteractive Elixir (1.11.1) - press Ctrl+C to exit (type h() ENTER for help)\niex[1]\u003e alias Tetris.Tetromino\nTetris.Tetromino\niex[2]\u003e Tetromino.__struct__  \n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[3]\u003e Tetromino.__struct__ |\u003e Map.keys\n[:__struct__, :location, :rotation, :shape]\niex[4]\u003e %{location: {5, 1}, rotation: 0, shape: :l}                \n%{location: {5, 1}, rotation: 0, shape: :l}\niex[5]\u003e %{location: {5, 1}, rotation: 0, shape: :l} |\u003e Map.keys\n[:location, :rotation, :shape]\niex[6]\u003e l = v(2)\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[7]\u003e l |\u003e Map.keys\n[:__struct__, :location, :rotation, :shape]\niex[8]\u003e l.__struct__\nTetris.Tetromino\niex[9]\u003e l.bad_key\n** (KeyError) key :bad_key not found in: %Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\n\niex[9]\u003e %{l | locatoin: {10, 10}}\n** (KeyError) key :locatoin not found in: %Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}. Did you mean one of:\n\n      * :location\n\n    (stdlib 3.13.2) :maps.update(:locatoin, {10, 10}, %Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l})\n    (stdlib 3.13.2) erl_eval.erl:259: anonymous fn/2 in :erl_eval.expr/5\n    (stdlib 3.13.2) lists.erl:1267: :lists.foldl/3\niex[9]\u003e Tetromino.__struct__\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[10]\u003e Tetromino.__struct__(shape: :o)\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :o}\niex[11]\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex[12]\u003e Tetromino.new\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[13]\u003e Tetromino.new(location: {10, 10})\n%Tetris.Tetromino{location: {10, 10}, rotation: 0, shape: :l}\niex[14]\u003e Tetromino.new(location: {10, 10}, shape: :t)\n%Tetris.Tetromino{location: {10, 10}, rotation: 0, shape: :t}\niex[15]\u003e [:a, :b, :c]\n[:a, :b, :c]\niex[16]\u003e ~w(a b c)\n[\"a\", \"b\", \"c\"]\niex[17]\u003e ~w(a b c)a\n[:a, :b, :c]\niex[18]\u003e ~w[a b c]a\n[:a, :b, :c]\niex[19]\u003e ~w/a b c/a\n[:a, :b, :c]\niex[20]\u003e ~w(i t o l j z s)a\n[:i, :t, :o, :l, :j, :z, :s]\niex[21]\u003e i\nTerm\n  [:i, :t, :o, :l, :j, :z, :s]\nData type\n  List\nReference modules\n  List\nImplemented protocols\n  Collectable, Enumerable, IEx.Info, Inspect, Jason.Encoder, List.Chars, Phoenix.HTML.Safe, Phoenix.Param, Plug.Exception, String.Chars\niex[22]\u003e i ~w(i t o l j z s)a\nTerm\n  [:i, :t, :o, :l, :j, :z, :s]\nData type\n  List\nReference modules\n  List\nImplemented protocols\n  Collectable, Enumerable, IEx.Info, Inspect, Jason.Encoder, List.Chars, Phoenix.HTML.Safe, Phoenix.Param, Plug.Exception, String.Chars\niex[23]\u003e exports Enum\nall?/1                all?/2                any?/1                any?/2                \nat/2                  at/3                  chunk/2               chunk/3               \nchunk/4               chunk_by/2            chunk_every/2         chunk_every/3         \nchunk_every/4         chunk_while/4         concat/1              concat/2              \ncount/1               count/2               dedup/1               dedup_by/2            \ndrop/2                drop_every/2          drop_while/2          each/2                \nempty?/1              fetch/2               fetch!/2              filter/2              \nfilter_map/3          find/2                find/3                find_index/2          \nfind_value/2          find_value/3          flat_map/2            flat_map_reduce/3     \nfrequencies/1         frequencies_by/2      group_by/2            group_by/3            \nintersperse/2         into/2                into/3                join/1                \njoin/2                map/2                 map_every/3           map_intersperse/3     \nmap_join/2            map_join/3            map_reduce/3          max/1                 \nmax/2                 max/3                 max_by/2              max_by/3              \nmax_by/4              member?/2             min/1                 min/2                 \nmin/3                 min_by/2              min_by/3              min_by/4              \nmin_max/1             min_max/2             min_max_by/2          min_max_by/3          \nmin_max_by/4          partition/2           random/1              reduce/2              \nreduce/3              reduce_while/3        reject/2              reverse/1             \nreverse/2             reverse_slice/3       scan/2                scan/3                \nshuffle/1             slice/2               slice/3               sort/1                \nsort/2                sort_by/2             sort_by/3             split/2               \nsplit_while/2         split_with/2          sum/1                 take/2                \ntake_every/2          take_random/2         take_while/2          to_list/1             \nuniq/1                uniq/2                uniq_by/2             unzip/1               \nwith_index/1          with_index/2          zip/1                 zip/2                 \niex[24]\u003e exports List\nascii_printable?/1     ascii_printable?/2     delete/2               delete_at/2            \nduplicate/2            first/1                flatten/1              flatten/2              \nfoldl/3                foldr/3                improper?/1            insert_at/3            \nkeydelete/3            keyfind/3              keyfind/4              keymember?/3           \nkeyreplace/4           keysort/2              keystore/4             keytake/3              \nlast/1                 myers_difference/2     myers_difference/3     pop_at/2               \npop_at/3               replace_at/3           starts_with?/2         to_atom/1              \nto_charlist/1          to_existing_atom/1     to_float/1             to_integer/1           \nto_integer/2           to_string/1            to_tuple/1             update_at/3            \nwrap/1                 zip/1                  \niex[25]\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex[26]\u003e Tetromino.new_random()\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :t}\niex[27]\u003e Tetromino.new_random()\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :j}\niex[28]\u003e Tetromino.new_random()\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :i}\niex[29]\u003e tetro = Tetromino.new()\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[30]\u003e %{tetro | location: {6, 1}}\n%Tetris.Tetromino{location: {6, 1}, rotation: 0, shape: :l}\niex[31]\u003e tetro\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[32]\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex[33]\u003e tetro\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[34]\u003e tetro |\u003e Tetromino.right()\n%Tetris.Tetromino{location: {6, 1}, rotation: 0, shape: :l}\niex[35]\u003e tetro |\u003e Tetromino.right() |\u003e Tetromino.down()\n%Tetris.Tetromino{location: {6, 2}, rotation: 0, shape: :l}\niex[36]\u003e recompile\nCompiling 1 file (.ex)\nwarning: variable \"tetro\" is unused (if the variable is not meant to be used, prefix it with an underscore)\n  lib/tetris/tetromino.ex:26: Tetris.Tetromino.rotate/1\n\n:ok\niex[37]\u003e Tetromino.rotate\nrotate/1            rotate_degrees/1    \niex[38]\u003e Tetromino.rotate_degrees(0)\n90\niex[39]\u003e Tetromino.rotate_degrees(0) |\u003e Tetromino.rotate_degrees()\n180\niex[40]\u003e Tetromino.rotate_degrees(0) |\u003e Tetromino.rotate_degrees() |\u003e Tetromino.rotate_degrees()\n270\niex[41]\u003e Tetromino.rotate_degrees(0) |\u003e Tetromino.rotate_degrees() |\u003e Tetromino.rotate_degrees() |\u003e Tetromino.rotate_degrees()\n0\niex[42]\u003e Tetromino.rotate_degrees(270)\n0\niex[43]\u003e recompile\nCompiling 1 file (.ex)\n:ok\niex[44]\u003e tetro\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\niex[45]\u003e tetro |\u003e Tetromino.rotate()\n%Tetris.Tetromino{location: {5, 1}, rotation: 90, shape: :l}\niex[46]\u003e tetro |\u003e Tetromino.rotate() |\u003e Tetromino.rotate()\n%Tetris.Tetromino{location: {5, 1}, rotation: 180, shape: :l}\niex[47]\u003e tetro |\u003e Tetromino.rotate() |\u003e Tetromino.rotate() |\u003e Tetromino.rotate()\n%Tetris.Tetromino{location: {5, 1}, rotation: 270, shape: :l}\niex[48]\u003e tetro |\u003e Tetromino.rotate() |\u003e Tetromino.rotate() |\u003e Tetromino.rotate() |\u003e Tetromino.rotate()\n%Tetris.Tetromino{location: {5, 1}, rotation: 0, shape: :l}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherminiotorres%2Ftetris","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fherminiotorres%2Ftetris","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherminiotorres%2Ftetris/lists"}