termworld 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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