1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# -*- coding: utf-8 -*-
require "set"
module Plugin::Achievement; end
class Plugin::Achievement::Achievement
attr_reader :slug, :plugin
def initialize(slug, plugin, options)
type_strict slug => Symbol, plugin => Plugin, options => Hash
@slug, @plugin, @options = slug, plugin, options
@events = Set.new
end
def hint ; @options[:hint] || "" end
def description ; @options[:description] || "" end
def hidden? ; @options[:hidden] end
# 解除されていれば真
def took?
(UserConfig[:achievement_took] || []).include? slug
end
# 解除する
def take!
unless took?
@events.each{ |e| plugin.detach(*e) }
@events.clear
if @options[:depends] and not @options[:depends].empty?
unachievements = Plugin.filtering(:unachievements, {}).first.values_at(*@options[:depends]).compact
if not unachievements.empty?
on_achievement_took do |ach|
if unachievements.delete(ach) and unachievements.empty?
_force_take! end end
return self end end
_force_take! end
self end
# 依存してる実績の中で、解除されてない最初の一つを返す
# ==== Return
# 見つかった実績(Plugin::Achievement::Achievement)
# 依存している実績がなかった場合や、全て解除済みの場合は self を返す
def notachieved_parent
unachievements = Plugin.filtering(:unachievements, {}).first
if @options[:depends]
result = @options[:depends].map{ |slug| unachievements[slug] }.compact.first
if result
result.notachieved_parent
else
self end
else
self end end
def method_missing(method, *args, &block)
result = plugin.__send__(method, *args, &block)
case method.to_s
when /\Aon_?(.*)\Z/
@events << [$1.to_sym, result]
when /\Afilter_?(.*)\Z/
@events << [$1.to_sym, result]
end
result
end
private
def _force_take!
UserConfig[:achievement_took] = (UserConfig[:achievement_took] || []) + [slug]
Plugin.call(:achievement_took, self) end
end
Plugin.create :achievement do
# 実績を定義する
# ==== Args
# [slug] 実績のスラッグ
# [options]
# :description 実績の説明。解除してから出ないと見れない。
# :hint 実績解除のヒント。解除する条件が整っていれば見れる。
# :depends 前提とする実績。実績スラッグの配列。
# :hidden 隠し実績(ヒントを出さない)の場合真
defdsl :defachievement do |slug, options, &block|
type_strict slug => Symbol, options => Hash
ach = Plugin::Achievement::Achievement.new(slug, self, options)
unless ach.took?
ach.filter_unachievements do |achievements|
achievements[slug] = ach unless ach.took?
[achievements]
end
filter_achievemented do |achievements|
achievements[slug] = ach if ach.took?
[achievements]
end
ach.instance_eval(&block)
end
end
defactivity "achievement", _("実績")
defachievement(:register_account,
description: _("Twitterアカウントをmikutterに登録しました。これでTwitterが捗る"),
hidden: true
) do |ach|
on_service_registered do |_| ach.take! end
end
defachievement(:open_setting,
description: _("設定画面で、mikutterをカスタマイズしましょう。"),
hint: _("画面右下にあるレンチのアイコンをクリックしよう"),
depends: [:register_account, :tutorial]
) do |ach|
on_open_setting do ach.take! end
end
defachievement(:display_requirements,
description: _("ヾ(@⌒ー⌒@)ノ"),
hint: _("https://github.com/toshia/display_requirements"),
depends: [:open_setting]
) do |ach|
Delayer.new {
dr = Plugin.instance(:display_requirements)
ach.take! unless dr and defined? dr.rotten? } end
defachievement(:multipane,
description: _("新規ペインを追加コマンドでペインを増やせます"),
hint: _("タブを右クリックして、「新規ペインに移動」をクリックしてみよう"),
depends: [:register_account, :tutorial]
) do |ach|
on_gui_pane_join_window do |pane, window|
if window.children.inject(0){|i,s| i + (s.is_a?(Plugin::GUI::Pane) ? 1 : 0) } >= 2
ach.take! end end end
defachievement(:move_pane,
description: _("タブを別のペインにドラッグすれば、そのペインに移動できます"),
hint: _("二つ以上ペインがある時に、タブを別のペインにドラッグ&ドロップしてみましょう"),
depends: [:multipane]
) do |ach|
on_after_gui_tab_reordered do |tab|
ach.take! end
on_after_gui_tab_reparent do |tab, old_pane, new_pane|
ach.take! end end
defachievement(:bugreporter,
description: _("クラッシュレポートの報告ありがとうございます"),
hidden: true,
depends: [:register_account, :tutorial]
) do |ach|
on_send_bugreport do |report|
ach.take! end end
defachievement(:hidden_command,
description: "隠しコマンドを入力した",
hidden: true,
depends: [:tutorial]
) do |ach|
on_konami_activate do
ach.take! end end
Delayer.new do
unachievements = Plugin.filtering(:unachievements, {}).first.reject{ |k, v| v.hidden? }
unless unachievements.empty?
not_achieved = unachievements.values.sample.notachieved_parent
unless not_achieved.hidden?
if Mopt.debug?
activity :achievement, "#{not_achieved.hint}\n(slug: #{not_achieved.slug})"
else
activity :achievement, not_achieved.hint end end end end
on_achievement_took do |achievement|
activity :achievement, (_("実績 %s を達成しました!おめでとう♪") % achievement.slug.to_s) end
end
|