termworld 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9fb28ea82445649a5fc0a168fe89ab394f821fde1b0afb9802fd9dabb0500aae
4
- data.tar.gz: 0eb3cf48ead8858ac5f54036086c029168d9422681caf7f19eeb1567cbfa5626
3
+ metadata.gz: fdd1aafdb9205075fd1e3a25f335a02236fe901e455e9e36d173b8354a0b33b9
4
+ data.tar.gz: d953f8661dded33034572c8f3eb3100e38a1f77875f40a00ab77fe25064e6952
5
5
  SHA512:
6
- metadata.gz: 81c855b5c4a77d064e88ba64273b72854cbd77f123f05a6fa3b08a79c84b62f9c2a5c71cec7363f17421ad687ce197ae1940b340fbdf8d4aa65257bea3abcf0a
7
- data.tar.gz: 04fd7e4e5ede01d5a5e6ae66c38b7a1fb0ad67b31175e8a53302eebaea9c27a3ccc0b8f8038d12f74c19ae02518d12b6d552091c709426eace507c7626031465
6
+ metadata.gz: 340f46ae87eec7fbc9482e0349e19fd980440d37eaf2e528fc613eeb806245be1c92518319ea0254af7d85fdc1d32191894cdb9ca8933b85a55d66b18d793b9d
7
+ data.tar.gz: 87fac115ba3651b040bc986deb7c06488fcde6c6cdf07e2511cd472675379eca09497e380de94ebf2671f170e548aa96ab954635d9264557566c8447236114aa
@@ -1,9 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- termworld (0.1.3)
4
+ termworld (0.2.0)
5
+ httpclient
5
6
  sequel
6
7
  sqlite3
8
+ term_canvas (= 0.2.9)
7
9
  thor
8
10
 
9
11
  GEM
@@ -11,7 +13,9 @@ GEM
11
13
  specs:
12
14
  byebug (11.0.1)
13
15
  coderay (1.1.2)
16
+ curses (1.3.1)
14
17
  diff-lcs (1.3)
18
+ httpclient (2.8.3)
15
19
  method_source (0.9.2)
16
20
  pry (0.12.2)
17
21
  coderay (~> 1.1.0)
@@ -24,17 +28,19 @@ GEM
24
28
  rspec-core (~> 3.8.0)
25
29
  rspec-expectations (~> 3.8.0)
26
30
  rspec-mocks (~> 3.8.0)
27
- rspec-core (3.8.0)
31
+ rspec-core (3.8.1)
28
32
  rspec-support (~> 3.8.0)
29
33
  rspec-expectations (3.8.4)
30
34
  diff-lcs (>= 1.2.0, < 2.0)
31
35
  rspec-support (~> 3.8.0)
32
- rspec-mocks (3.8.0)
36
+ rspec-mocks (3.8.1)
33
37
  diff-lcs (>= 1.2.0, < 2.0)
34
38
  rspec-support (~> 3.8.0)
35
39
  rspec-support (3.8.2)
36
40
  sequel (5.21.0)
37
41
  sqlite3 (1.4.1)
42
+ term_canvas (0.2.9)
43
+ curses
38
44
  thor (0.20.3)
39
45
 
40
46
  PLATFORMS
@@ -1,13 +1,23 @@
1
- require "thor"
2
1
  require "sequel"
3
2
 
4
- require "termworld/constants/version"
5
- require "termworld/db/db"
3
+ require "termworld/config"
4
+ require "termworld/utils/color"
5
+ require "termworld/utils/api_client"
6
6
  require "termworld/cli"
7
+ require "termworld/daemon"
7
8
 
8
9
  module Termworld
9
10
  def self.start
10
- DB.new
11
+ setup_termworld_directory
12
+ $api_client = Utils::ApiClient.new
13
+ $db = Sequel.sqlite(Termworld::DATABASE_NAME) if Daemon.new.alive?
11
14
  CLI.start
12
15
  end
16
+
17
+ def self.setup_termworld_directory
18
+ directory = Termworld::HOME_DIRECTORY_NAME
19
+ Dir::chdir(Dir::home)
20
+ Dir::mkdir(directory) unless Dir::exists?(directory)
21
+ Dir::chdir(directory)
22
+ end
13
23
  end
@@ -1,9 +1,53 @@
1
+ require "thor"
2
+ require "json"
3
+
4
+ require "termworld/db"
5
+ require "termworld/commands/account"
6
+ require "termworld/commands/daemon_operator"
7
+ require "termworld/commands/user"
8
+ require "termworld/commands/user_action"
9
+ require "termworld/credential"
10
+ require "termworld/utils/option_parser_wrapper"
11
+
1
12
  module Termworld
2
13
  class CLI < Thor
3
14
 
4
- desc "start", "Start game client..."
15
+ desc "login", "Login"
16
+ def login
17
+ Commands::Account.login
18
+ end
19
+ desc "logout", "Logout"
20
+ def logout
21
+ Commands::Account.logout
22
+ end
23
+
24
+ desc "start", "Start game client"
5
25
  def start
6
- puts :starting
26
+ Commands::DaemonOperator.start
27
+ end
28
+ desc "stop", "Stop game client"
29
+ def stop
30
+ Commands::DaemonOperator.stop
31
+ end
32
+ desc "status", "Check status"
33
+ def status
34
+ Commands::DaemonOperator.status
35
+ end
36
+
37
+ desc "user [COMMAND] <options>", "User actions"
38
+ subcommand "user", Commands::User
39
+
40
+ def method_missing(method, *arg, &block)
41
+ _method = method.to_s.split(?:)
42
+ begin
43
+ action_class = Object.const_get("Termworld::Commands::#{_method[0].capitalize}Action")
44
+ rescue
45
+ puts Utils::Color.reden "#{_method[0]} command not found"
46
+ return
47
+ end
48
+ action = action_class.new(_method[1])
49
+ return puts Utils::Color.reden "Enter any commands" if arg.empty?
50
+ action.send(arg[0], arg[1..-1])
7
51
  end
8
52
  end
9
53
  end
@@ -0,0 +1,35 @@
1
+ module Termworld
2
+ module Commands
3
+ class Account
4
+ class << self
5
+ def login
6
+ credential = Credential.new
7
+ return puts Utils::Color.reden "Already logged in" if credential.logged_in?
8
+ print "email: "
9
+ email = $stdin.gets.chomp
10
+ res = $api_client.call(:post, '/token', {email: email})
11
+ return puts Utils::Color.reden "Invalid email" if res.code != 200
12
+ puts Utils::Color.greenen "Sent token to your email, please input below"
13
+ print "token: "
14
+ token = $stdin.gets.chomp
15
+ res = $api_client.call(:post, '/login', {email: email, token: token})
16
+ return puts Utils::Color.reden "Invalid token" if res.code != 200
17
+ File.write(Termworld::CREDENTIAL_FILE_NAME, "#{email}\n#{token}")
18
+ puts Utils::Color.greenen "Login successed!"
19
+ end
20
+
21
+ def logout
22
+ credential = Credential.new
23
+ return puts Utils::Color.reden "Not logged in" unless credential.logged_in?
24
+ email, token = Credential.get_credential
25
+ res = $api_client.call(:post, '/logout', {email: email, token: token})
26
+ return puts Utils::Color.reden "Logout failed" if res.code != 200
27
+ daemon = Daemon.new(:logout)
28
+ daemon.stop if daemon.alive?
29
+ File.delete(Termworld::CREDENTIAL_FILE_NAME) if File.exists?(Termworld::CREDENTIAL_FILE_NAME)
30
+ puts Utils::Color.greenen "Logout successed!"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ module Termworld
2
+ module Commands
3
+ class DaemonOperator
4
+ class << self
5
+ def start
6
+ credential = Credential.new
7
+ return puts credential.error_message unless credential.logged_in?
8
+ daemon = Daemon.new(:start)
9
+ return puts daemon.error_message if daemon.error_message
10
+ daemon.prepare
11
+ puts Utils::Color.greenen "Started!"
12
+ daemon.run
13
+
14
+ loop do
15
+ break unless daemon.alive?
16
+ sleep 1
17
+ end
18
+ daemon.stop
19
+ end
20
+
21
+ def stop
22
+ credential = Credential.new
23
+ daemon = Daemon.new(:stop)
24
+ unless credential.logged_in?
25
+ daemon.stop
26
+ return puts credential.error_message
27
+ end
28
+ if daemon.error_message
29
+ daemon.delete_files
30
+ return puts daemon.error_message
31
+ end
32
+ daemon.stop
33
+ puts Utils::Color.greenen "Stopped!"
34
+ end
35
+
36
+ def status
37
+ credential = Credential.new
38
+ return puts credential.error_message unless credential.logged_in?
39
+ daemon = Daemon.new(:status)
40
+ return puts daemon.error_message if daemon.error_message
41
+ if daemon.alive?
42
+ puts Utils::Color.bluen "Running!"
43
+ else
44
+ puts Utils::Color.bluen "Not running."
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ module Termworld
2
+ module Commands
3
+ class User < Thor
4
+
5
+ desc "create", "Create user"
6
+ def create(*options)
7
+ option_parser = Utils::OptionParserWrapper.new([
8
+ {option: ['-n', '--name [VALUE]', 'User name'], key: :name},
9
+ ])
10
+ params = option_parser.parse!
11
+ return puts option_parser.error_message if option_parser.error_message
12
+ if params[:name].nil?
13
+ print "name: "
14
+ params[:name] = $stdin.gets.chomp
15
+ end
16
+
17
+ user = Models::User.new(params)
18
+ result = user.create
19
+ return puts Utils::Color.reden "Failed create user" unless result
20
+ puts Utils::Color.greenen "Successed create user!"
21
+ end
22
+
23
+ desc "list", "List users"
24
+ def list(*options)
25
+ option_parser = Utils::OptionParserWrapper.new([])
26
+ option_parser.parse!
27
+ return puts option_parser.error_message if option_parser.error_message
28
+
29
+ users = Models::User.all
30
+ if users.empty?
31
+ puts Utils::Color.bluen "No users. Please create user first"
32
+ puts "ex) $ termworld user create --name=<name>"
33
+ return
34
+ end
35
+ users.each do |user|
36
+ puts "id:#{user.id} #{user.name}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ require "termworld/terminal/controller"
2
+
3
+ module Termworld
4
+ module Commands
5
+ class UserAction
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def wakeup(options)
11
+ res = $api_client.call_auth(:get, "/users/#{@name}")
12
+ puts Utils::Color.reden "Login required" if res.code == 401
13
+ puts Utils::Color.reden "User:#{@name} doesn't exsit" if res.code == 404
14
+ user = Models::User.new(JSON.parse(res.body, {symbolize_names: true})[:user])
15
+ user.initialize_position
16
+ user.save_local
17
+ if user.updated
18
+ puts Utils::Color.reden "User:#{user.name} already awake"
19
+ elsif user.created
20
+ puts Utils::Color.greenen "User:#{user.name} woke up!"
21
+ end
22
+ end
23
+
24
+ def sleep(options)
25
+ user = Models::User.new(name: @name)
26
+ user.delete_local(by: :name)
27
+ puts Utils::Color.greenen "User:#{user.name} slept!"
28
+ end
29
+
30
+ def terminal(options)
31
+ user = Models::User.new(name: @name)
32
+ if !user.bind_local_by_name
33
+ return puts Utils::Color.reden "User:#{@name} is not awake or doesn't exists"
34
+ end
35
+ terminal = Terminal::Controller.new(user)
36
+ terminal.run
37
+ end
38
+
39
+ def move(options)
40
+ if options.size != 1 || !%w(up down left right).include?(options.first)
41
+ puts Utils::Color.reden 'Direction must be only up, down, left or right'
42
+ puts "ex) $ termworld user:#{@name} move up"
43
+ return
44
+ end
45
+ direction = options.first.to_sym
46
+ user = Models::User.new(name: @name)
47
+ if !user.bind_local_by_name
48
+ return puts Utils::Color.reden "User:#{@name} is not awake or doesn't exists"
49
+ end
50
+ user.move(direction)
51
+ end
52
+
53
+ def method_missing(method, _)
54
+ puts Utils::Color.reden "#{method} command not found"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,8 @@
1
+ module Termworld
2
+ HOME_DIRECTORY_NAME = '.termworld'
3
+ DAEMON_FILE_NAME = 'daemon'
4
+ PROCESS_NAME = 'termworld_daemon'
5
+ DATABASE_NAME = 'termworld.db'
6
+ CREDENTIAL_FILE_NAME = 'credential'
7
+ API_ENDPOINT = 'http://0.0.0.0:3000'
8
+ end
@@ -0,0 +1,34 @@
1
+ module Termworld
2
+ class Credential
3
+ attr_reader :error_message
4
+ def logged_in?
5
+ if !File.exists?(Termworld::CREDENTIAL_FILE_NAME)
6
+ @error_message = Utils::Color.reden "Login required"
7
+ return false
8
+ end
9
+ email, token = Credential.get_credential
10
+ File.open(Termworld::CREDENTIAL_FILE_NAME) do |file|
11
+ email, token = file.read.split("\n")
12
+ end
13
+ res = $api_client.call(:post, '/login', {email: email, token: token})
14
+ if res.code != 200
15
+ @error_message = Utils::Color.reden "Wrong credential\nPlease login again"
16
+ return false
17
+ end
18
+ true
19
+ end
20
+ class << self
21
+ def get_credential
22
+ email, token = nil
23
+ begin
24
+ File.open(Termworld::CREDENTIAL_FILE_NAME) do |file|
25
+ email, token = file.read.split("\n")
26
+ end
27
+ rescue
28
+ return [nil, nil]
29
+ end
30
+ [email, token]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,55 @@
1
+ module Termworld
2
+ class Daemon
3
+ attr_reader :error_message
4
+ def initialize(status = nil)
5
+ case status
6
+ when :start
7
+ @error_message = Utils::Color.reden "Already running" if alive?
8
+ when :stop
9
+ @error_message = Utils::Color.reden "Not running" unless alive?
10
+ end
11
+ end
12
+
13
+ def prepare
14
+ delete_files
15
+ [:INT, :TERM].each do |key|
16
+ Signal.trap(key) {@killed = true}
17
+ end
18
+ DB.setup
19
+ Process.setproctitle(Termworld::PROCESS_NAME)
20
+ File.write(Termworld::DAEMON_FILE_NAME, nil)
21
+ end
22
+
23
+ def run
24
+ Process.daemon(true, false) # (nochdir, noclose)
25
+ end
26
+
27
+ def alive?
28
+ @killed.nil? && daemon_file_exists && daemon_process_exists
29
+ end
30
+
31
+ def stop
32
+ delete_files
33
+ kill_daemon_process
34
+ end
35
+
36
+ def delete_files
37
+ File.delete(Termworld::DAEMON_FILE_NAME) if File.exists?(Termworld::DAEMON_FILE_NAME)
38
+ File.delete(Termworld::DATABASE_NAME) if File.exists?(Termworld::DATABASE_NAME)
39
+ end
40
+
41
+ private
42
+
43
+ def kill_daemon_process
44
+ `ps aux | grep #{Termworld::PROCESS_NAME} | grep -v grep | awk '{print $2}' | xargs kill`
45
+ end
46
+
47
+ def daemon_file_exists
48
+ File.exists?(Termworld::DAEMON_FILE_NAME)
49
+ end
50
+
51
+ def daemon_process_exists
52
+ `ps aux | grep #{Termworld::PROCESS_NAME} | grep -v grep | wc -l`.delete(' ').to_i > 0
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,12 @@
1
+ require "termworld/models/user"
2
+
3
+ module Termworld
4
+ class DB
5
+ class << self
6
+ def setup
7
+ $db ||= Sequel.sqlite(Termworld::DATABASE_NAME)
8
+ Models::User.create_table
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,127 @@
1
+ module Termworld
2
+ module Models
3
+ class User
4
+ attr_reader :id, :name, :created, :updated, :positionx, :positiony
5
+ class << self
6
+ def create_table
7
+ $db.create_table :users do
8
+ primary_key :id
9
+ String :name
10
+ String :current_map_name
11
+ Integer :positionx
12
+ Integer :positiony
13
+ end
14
+ end
15
+
16
+ def all
17
+ res = $api_client.call_auth(:get, '/users')
18
+ return [] if res.code != 200
19
+ JSON.parse(res.body, {symbolize_names: true})[:users].map do |user|
20
+ self.new(user)
21
+ end
22
+ end
23
+
24
+ def all_local
25
+ $db[:users].all.map do |user|
26
+ self.new(user)
27
+ end
28
+ end
29
+ end
30
+
31
+ def initialize(params)
32
+ params.each { |key, value| instance_variable_set("@#{key}", value) }
33
+ end
34
+
35
+ def bind_local_by_name
36
+ record = $db[:users].where(name: @name).first
37
+ return false if record.nil?
38
+ record.reject { |key, _| key == :name }.each { |key, value|
39
+ instance_variable_set("@#{key}", value)
40
+ }
41
+ true
42
+ end
43
+
44
+ def create
45
+ validate
46
+ return false unless @errors.empty?
47
+ res = $api_client.call_auth(:post, '/users', {name: @name})
48
+ return false if res.code != 201
49
+ true
50
+ end
51
+ def save_local
52
+ validate
53
+ return false unless @errors.empty?
54
+ if record = $db[:users].where(id: @id).first
55
+ @created, @updated = false, true
56
+ $db[:users].where(id: @id).update(attributes_without_id)
57
+ else
58
+ @created, @updated = true, false
59
+ $db[:users].insert(attributes)
60
+ end
61
+ end
62
+ def delete_local(by: nil)
63
+ if by == :id
64
+ $db[:users].where(id: @id).delete
65
+ elsif by == :name
66
+ $db[:users].where(name: @name).delete
67
+ end
68
+ end
69
+
70
+ def validate
71
+ @errors = []
72
+ if @name.nil? || @name.empty?
73
+ @errors << "Name is required"
74
+ elsif !@name.scan(/[^0-9a-z]+/i).empty?
75
+ @errors << "Name must be only alphanumeric"
76
+ end
77
+ end
78
+
79
+ def attributes
80
+ {
81
+ id: @id,
82
+ name: @name,
83
+ current_map_name: @current_map_name,
84
+ positionx: @positionx,
85
+ positiony: @positiony,
86
+ }
87
+ end
88
+ def attributes_without_id
89
+ attributes.reject { |k, _| k == :id }
90
+ end
91
+
92
+ def initialize_position
93
+ @current_map_name = 'town'
94
+ @positionx = 0
95
+ @positiony = 0
96
+ end
97
+
98
+ def move(direction)
99
+ supposed_position = {x: @positionx, y: @positiony}
100
+ case direction
101
+ when :up
102
+ supposed_position[:y] -= 1
103
+ when :down
104
+ supposed_position[:y] += 1
105
+ when :left
106
+ supposed_position[:x] -= 1
107
+ when :right
108
+ supposed_position[:x] += 1
109
+ else
110
+ return false
111
+ end
112
+ return false if supposed_position.any? { |_, v| v < 0 }
113
+ chip = current_map.get_chip(supposed_position)
114
+ return false if chip.nil? || !chip.movable
115
+ @positionx = supposed_position[:x]
116
+ @positiony = supposed_position[:y]
117
+ save_local
118
+ true
119
+ end
120
+
121
+ def current_map
122
+ @current_map ||= Object.const_get("Termworld::Resources::Maps::#{@current_map_name.capitalize}").new
123
+ @current_map
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,41 @@
1
+ require "term_canvas"
2
+
3
+ module Termworld
4
+ module Resources
5
+ class Chip
6
+ attr_reader :movable
7
+ def initialize(y: nil, x: nil, key:)
8
+ @y = y
9
+ @x = x
10
+ @key = key
11
+ data
12
+ end
13
+
14
+ def data
15
+ case @key
16
+ when "00"
17
+ @movable = true
18
+ {
19
+ background_color: {r: 300, g: 300, b: 300},
20
+ }
21
+ when "01"
22
+ @movable = false
23
+ {
24
+ background_color: {r: 0, g: 0, b: 0},
25
+ }
26
+ when "pl"
27
+ {
28
+ background_color: {r: 200, b: 200, g: 800},
29
+ }
30
+ end
31
+ end
32
+
33
+ def rect
34
+ TermCanvas::Rect.new(
35
+ x: @x, y: @y, width: 2, height: 1,
36
+ background_color: data[:background_color],
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ module Termworld
2
+ module Resources
3
+ module Maps
4
+ class Town
5
+ def chip_numbers
6
+ return @chip_numbers_lines if @chip_numbers_lines
7
+ chip_numbers_lines = <<'EOS'
8
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
10
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11
+ 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
12
+ 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13
+ 00 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
14
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
15
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
17
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
18
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
19
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
21
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
23
+ EOS
24
+ @chip_numbers_lines = chip_numbers_lines.lines(chomp: true)
25
+ .map { |chip_numbers_line| chip_numbers_line.split }
26
+ @chip_numbers_lines
27
+ end
28
+ def get_chip(y:, x:)
29
+ chip_number = chip_numbers[y] && chip_numbers[y][x]
30
+ return nil if chip_number.nil?
31
+ chip = Resources::Chip.new(y: y, x: x, key: chip_number)
32
+ chip
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,74 @@
1
+ require "term_canvas"
2
+
3
+ require "termworld/resources/chip"
4
+ require "termworld/resources/maps/town"
5
+
6
+ module Termworld
7
+ module Terminal
8
+ class Controller
9
+ def initialize(user)
10
+ @user = user
11
+ end
12
+
13
+ def run
14
+ field = TermCanvas::Canvas.new(x: 0, y: 0, w: TermCanvas.width, h: TermCanvas.height)
15
+
16
+ map = Resources::Maps::Town.new
17
+ loop do
18
+ @user.bind_local_by_name
19
+ users = Models::User.all_local.reject { |user| user.name == @user.name }
20
+
21
+ break if handle_keys == :break
22
+ field.clear
23
+
24
+ height = field.height
25
+ width = field.width / 2 - 1
26
+ height.times do |y|
27
+ width.times do |x|
28
+ abs_position = {
29
+ x: @user.positionx - (width / 2) + x,
30
+ y: @user.positiony - (height / 2) + y,
31
+ }
32
+ user = users.find { |u|
33
+ u.positionx == abs_position[:x] && u.positiony == abs_position[:y]
34
+ }
35
+ if user
36
+ player_chip = Resources::Chip.new(x: x * 2 + 1, y: y, key: "pl")
37
+ field.rect(player_chip.rect)
38
+ next
39
+ end
40
+ next if abs_position.any? { |_, v| v < 0 }
41
+ next if (chip = map.get_chip(abs_position)).nil?
42
+ field.rect(chip.rect.position_override(x: x * 2 + 1, y: y))
43
+ end
44
+ end
45
+
46
+ player_chip = Resources::Chip.new(x: field.centerx, y: field.centery, key: "pl")
47
+ field.rect(player_chip.rect)
48
+
49
+ field.update
50
+ sleep 0.05
51
+ end
52
+ TermCanvas.close
53
+ end
54
+
55
+ private
56
+
57
+ def handle_keys
58
+ key = TermCanvas.gets
59
+ case key
60
+ when ?q
61
+ return :break
62
+ when ?h
63
+ @user.move(:left)
64
+ when ?j
65
+ @user.move(:down)
66
+ when ?k
67
+ @user.move(:up)
68
+ when ?l
69
+ @user.move(:right)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ require "httpclient"
2
+
3
+ module Termworld
4
+ module Utils
5
+ class ApiClient
6
+
7
+ def initialize
8
+ @client = HTTPClient.new
9
+ end
10
+
11
+ def call(method, url, params = nil)
12
+ if method == :get
13
+ res = @client.get(Termworld::API_ENDPOINT + url, query: params)
14
+ else
15
+ res = @client.send(method, Termworld::API_ENDPOINT + url, body: params)
16
+ end
17
+ res
18
+ end
19
+
20
+ def call_auth(method, url, params = nil)
21
+ email, token = Credential.get_credential
22
+ headers = {
23
+ 'X-Termworld-Email': email,
24
+ 'X-Termworld-Token': token,
25
+ }
26
+ if method == :get
27
+ res = @client.get(Termworld::API_ENDPOINT + url, query: params, header: headers)
28
+ else
29
+ res = @client.send(method, Termworld::API_ENDPOINT + url, body: params, header: headers)
30
+ end
31
+ res
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ module Termworld
2
+ module Utils
3
+ class Color
4
+ class << self
5
+ def reden(str)
6
+ "\e[31m#{str}\e[0m"
7
+ end
8
+ def greenen(str)
9
+ "\e[32m#{str}\e[0m"
10
+ end
11
+ def yellowen(str)
12
+ "\e[33m#{str}\e[0m"
13
+ end
14
+ def bluen(str)
15
+ "\e[34m#{str}\e[0m"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ require "optparse"
2
+
3
+ module Termworld
4
+ module Utils
5
+ class OptionParserWrapper
6
+ attr_reader :error_message
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+ def parse!
11
+ params = {}
12
+ begin
13
+ OptionParser.new do |op|
14
+ @options.each do |option|
15
+ op.on(*option[:option]) { |v| params[option[:key]] = v }
16
+ end
17
+ op.parse!(params)
18
+ end
19
+ rescue OptionParser::InvalidOption => e
20
+ @error_message = Utils::Color.reden "Invalid options: #{e.args.first}"
21
+ return {}
22
+ end
23
+ params
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module Termworld
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  lib = File.expand_path("../lib", __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "termworld"
3
+ require "termworld/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "termworld"
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "thor"
24
24
  spec.add_dependency "sequel"
25
25
  spec.add_dependency "sqlite3"
26
+ spec.add_dependency "httpclient"
27
+ spec.add_dependency "term_canvas", "0.2.9"
26
28
 
27
29
  spec.add_development_dependency "bundler", "~> 2.0"
28
30
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: termworld
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kthatoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-18 00:00:00.000000000 Z
11
+ date: 2019-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: httpclient
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: term_canvas
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.2.9
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.9
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -132,9 +160,22 @@ files:
132
160
  - exe/termworld
133
161
  - lib/termworld.rb
134
162
  - lib/termworld/cli.rb
135
- - lib/termworld/constants/version.rb
136
- - lib/termworld/db/db.rb
137
- - lib/termworld/db/user.rb
163
+ - lib/termworld/commands/account.rb
164
+ - lib/termworld/commands/daemon_operator.rb
165
+ - lib/termworld/commands/user.rb
166
+ - lib/termworld/commands/user_action.rb
167
+ - lib/termworld/config.rb
168
+ - lib/termworld/credential.rb
169
+ - lib/termworld/daemon.rb
170
+ - lib/termworld/db.rb
171
+ - lib/termworld/models/user.rb
172
+ - lib/termworld/resources/chip.rb
173
+ - lib/termworld/resources/maps/town.rb
174
+ - lib/termworld/terminal/controller.rb
175
+ - lib/termworld/utils/api_client.rb
176
+ - lib/termworld/utils/color.rb
177
+ - lib/termworld/utils/option_parser_wrapper.rb
178
+ - lib/termworld/version.rb
138
179
  - termworld.gemspec
139
180
  homepage: https://github.com/kthatoto/termworld
140
181
  licenses:
@@ -1,10 +0,0 @@
1
- require "termworld/db/user"
2
-
3
- module Termworld
4
- class DB
5
- def initialize
6
- $db = Sequel.sqlite('./termworld.db')
7
- User.new
8
- end
9
- end
10
- end
@@ -1,11 +0,0 @@
1
- module Termworld
2
- class User
3
- def initialize
4
- $db.create_table :users do
5
- primary_key :id
6
- String :name
7
- Integer :price
8
- end
9
- end
10
- end
11
- end