fork(1) download
  1. package main
  2.  
  3. import (
  4. "bufio"
  5. "fmt"
  6. "math/rand"
  7. "os"
  8. "time"
  9. )
  10.  
  11. //ドアにはノブがついている
  12. //ノブを回すとラッチ解除、戻すとラッチ復元
  13. //ラッチON→ドア開かない
  14. //ドアストッパー
  15. // ドア閉まらない
  16. // ドア開けたら解除
  17. //ドアクローザー
  18. //一定時間でドアしまる
  19.  
  20. type eventMsg interface {
  21. opname() string
  22. }
  23.  
  24. //オペレーションたち
  25. type push struct{}
  26.  
  27. func (push) opname() string { return "Push" }
  28.  
  29. type pull struct{}
  30.  
  31. func (pull) opname() string { return "Pull" }
  32.  
  33. type dooropen struct{}
  34.  
  35. func (dooropen) opname() string { return "doorOpen" }
  36.  
  37. type dooropened struct{}
  38.  
  39. func (dooropened) opname() string { return "doorOpened" }
  40.  
  41. type dooropenfail struct{}
  42.  
  43. func (dooropenfail) opname() string { return "doorOpenFail" }
  44.  
  45. type doorclose struct{}
  46.  
  47. func (doorclose) opname() string { return "doorClose" }
  48.  
  49. type doorclosed struct{}
  50.  
  51. func (doorclosed) opname() string { return "doorClosed" }
  52.  
  53. type doorclosefail struct{}
  54.  
  55. func (doorclosefail) opname() string { return "doorCloseFail" }
  56.  
  57. type twist struct{}
  58.  
  59. func (twist) opname() string { return "twist" }
  60.  
  61. type twistback struct{}
  62.  
  63. func (twistback) opname() string { return "twistback" }
  64.  
  65. type lockopen struct{}
  66.  
  67. func (lockopen) opname() string { return "lock_open" }
  68.  
  69. type unlockopen struct{}
  70.  
  71. func (unlockopen) opname() string { return "unlock_open" }
  72.  
  73. type lockclose struct{}
  74.  
  75. func (lockclose) opname() string { return "lock_close" }
  76.  
  77. type unlockclose struct{}
  78.  
  79. func (unlockclose) opname() string { return "unlock_close" }
  80.  
  81. type setautoclose struct{}
  82.  
  83. func (setautoclose) opname() string { return "set_autoclose" }
  84.  
  85. type removeautoclose struct{}
  86.  
  87. func (removeautoclose) opname() string { return "remove_autoclose" }
  88.  
  89. //Enum
  90. type doorStat int
  91.  
  92. const (
  93. Opened doorStat = iota
  94. Closed
  95. )
  96.  
  97. type lockStat int
  98.  
  99. const (
  100. UnLocked lockStat = iota
  101. Locked
  102. )
  103.  
  104. func createAndExecProcMulti(inch chan eventMsg, outch []chan eventMsg, proc func(op eventMsg, outch []chan eventMsg)) {
  105. go func(inch chan eventMsg, outch []chan eventMsg) {
  106. for {
  107. go proc(<-inch, outch)
  108. }
  109. }(inch, outch)
  110. }
  111. func createAndExecProc(inch chan eventMsg, outch chan eventMsg, proc func(op eventMsg, outch chan eventMsg)) {
  112. go func(inch chan eventMsg, outch chan eventMsg) {
  113. for {
  114. go proc(<-inch, outch)
  115. }
  116. }(inch, outch)
  117. }
  118.  
  119. func main() {
  120. //ドア
  121. doorCh := make(chan eventMsg, 0)
  122. //ストッパー
  123. stopperCh := make(chan eventMsg, 0)
  124. //ラッチ?
  125. latchCh := make(chan eventMsg, 0)
  126. //ドアノブ
  127. knobCh := make(chan eventMsg, 0)
  128. //オートクローザー
  129. autocloserCh := make(chan eventMsg, 0)
  130.  
  131. //Door処理
  132. go func(inch chan eventMsg, outch []chan eventMsg) {
  133. //ドアの都合変数を隠したいので、createAndExecProcMulti使わず
  134. doorStatus := Closed
  135. openLockStat := Locked
  136. closeLockStat := UnLocked
  137. for {
  138. op := <-inch
  139. go func(op eventMsg) {
  140. switch op.(type) {
  141. case push:
  142. var msg eventMsg
  143. if doorStatus == Closed && openLockStat == UnLocked {
  144. doorStatus = Opened
  145. fmt.Println("****Door open!!")
  146. msg = dooropen{}
  147. } else {
  148. if doorStatus == Opened {
  149. fmt.Println("Door already open")
  150. msg = dooropened{}
  151. } else {
  152. fmt.Println("Door try to open,but failed")
  153. msg = dooropenfail{}
  154. }
  155. }
  156. for _, ch := range outch {
  157. ch <- msg
  158. }
  159. case pull:
  160. var msg eventMsg
  161. if doorStatus == Opened && closeLockStat == UnLocked {
  162. doorStatus = Closed
  163. fmt.Println("****Door Close!!")
  164. msg = doorclose{}
  165. } else {
  166. if doorStatus == Closed {
  167. fmt.Println("Door already closed")
  168. msg = doorclosed{}
  169. } else {
  170. fmt.Println("Door try to close,but failed")
  171. msg = doorclosefail{}
  172. }
  173. }
  174. for _, ch := range outch {
  175. ch <- msg
  176. }
  177. case lockopen:
  178. openLockStat = Locked
  179. fmt.Println("Door Open Locked")
  180. case unlockopen:
  181. openLockStat = UnLocked
  182. fmt.Println("Door Open UnLocked")
  183. case lockclose:
  184. closeLockStat = Locked
  185. fmt.Println("Door Close Locked")
  186. case unlockclose:
  187. closeLockStat = UnLocked
  188. fmt.Println("Door Close UnLocked")
  189. default:
  190. fmt.Printf("Door don't recognize %s\n", op.opname())
  191. }
  192. }(op)
  193. }
  194. }(doorCh, []chan eventMsg{stopperCh}) //ドア→いろんなもの。オートクローザとか?
  195. //Knob
  196. //ノブ→ラッチ
  197. createAndExecProc(knobCh, latchCh, func(op eventMsg, outch chan eventMsg) {
  198. switch op.(type) {
  199. case twist:
  200. fmt.Println("knob twisted")
  201. outch <- unlockopen{}
  202. case twistback:
  203. fmt.Println("knob untwisted")
  204. outch <- lockopen{}
  205. default:
  206. fmt.Printf("knob don't recognize %s\n", op.opname())
  207. }
  208. })
  209.  
  210. //ラッチ→ドア
  211. createAndExecProc(latchCh, doorCh, func(op eventMsg, outch chan eventMsg) {
  212. switch op.(type) {
  213. case unlockopen:
  214. fmt.Println("latch open")
  215. outch <- unlockopen{}
  216. case lockopen:
  217. fmt.Println("latch lock")
  218. outch <- lockopen{}
  219. default:
  220. fmt.Printf("Latch don't recognize %s\n", op.opname())
  221. }
  222. })
  223. //stopper
  224.  
  225. createAndExecProc(stopperCh, doorCh, func(op eventMsg, outch chan eventMsg) {
  226. switch op.(type) {
  227. case dooropen, dooropened, unlockclose:
  228. fmt.Println("stopper unlock")
  229. outch <- unlockclose{}
  230. case lockclose:
  231. fmt.Println("stopper lock")
  232. outch <- lockclose{}
  233. default:
  234. fmt.Printf("stopper don't recognize %s\n", op.opname())
  235. }
  236. })
  237. //オートクローザーとやら
  238. createAndExecProc(autocloserCh, doorCh, func(op eventMsg, outch chan eventMsg) {
  239. switch op.(type) {
  240. case setautoclose:
  241. fmt.Println("3")
  242. time.Sleep(time.Second * 1)
  243. fmt.Println("2")
  244. time.Sleep(time.Second * 1)
  245. fmt.Println("1")
  246. time.Sleep(time.Second * 1)
  247. fmt.Println("autocloser pulls door")
  248. outch <- pull{}
  249. default:
  250. fmt.Printf("stopper don't recognize %s\n", op.opname())
  251. }
  252. })
  253. //ユーザ入力
  254. scanner := bufio.NewScanner(os.Stdin)
  255. fmt.Println("You can input [Object] [Verbs] ")
  256. fmt.Println("door push/pull ")
  257. fmt.Println("knob twist/release")
  258. fmt.Println("stopper set/release")
  259. fmt.Println("autocloser set")
  260. fmt.Println("monkey !")
  261. for {
  262. for scanner.Scan() {
  263. var o = ""
  264. var v = ""
  265. _, err := fmt.Sscanf(scanner.Text(), "%s %s\n", &o, &v)
  266. if err != nil {
  267. //fmt.Printf("%+v", err)
  268. continue
  269. }
  270. fmt.Printf(">>%s,%s\n", o, v)
  271. if o == "monkey" && v == "!" {
  272. rand.Seed(time.Now().UnixNano())
  273. for {
  274. n := rand.Intn(3) //Autocloserは面白くない
  275. p := rand.Intn(2)
  276. var ch chan eventMsg
  277. var cmd eventMsg
  278. switch n {
  279. case 0:
  280. ch = doorCh
  281. if p == 0 {
  282. cmd = push{}
  283. } else {
  284. cmd = pull{}
  285. }
  286. case 1:
  287. ch = knobCh
  288. if p == 0 {
  289. cmd = twist{}
  290. } else {
  291. cmd = twistback{}
  292. }
  293. case 2:
  294. ch = stopperCh
  295. if p == 0 {
  296. cmd = lockclose{}
  297. } else {
  298. cmd = unlockclose{}
  299. }
  300. case 3:
  301. ch = autocloserCh
  302. cmd = setautoclose{}
  303. }
  304. ch <- cmd
  305. //これはずすとGC間に合わない
  306. time.Sleep(time.Millisecond * 1)
  307. }
  308.  
  309. }
  310. if o == "door" {
  311. if v == "push" {
  312. doorCh <- push{}
  313. }
  314. if v == "pull" {
  315. doorCh <- pull{}
  316. }
  317. }
  318. if o == "knob" {
  319. if v == "twist" {
  320. knobCh <- twist{}
  321. }
  322. if v == "release" {
  323. knobCh <- twistback{}
  324. }
  325. }
  326. if o == "stopper" {
  327. if v == "set" {
  328. stopperCh <- lockclose{}
  329. }
  330. if v == "release" {
  331. stopperCh <- unlockclose{}
  332. }
  333. }
  334. if o == "autocloser" {
  335. if v == "set" {
  336. autocloserCh <- setautoclose{}
  337. }
  338. }
  339. time.Sleep(time.Millisecond * 500) //ideone早いから。ターミナルでは不要
  340. }
  341. if err := scanner.Err(); err != nil {
  342. fmt.Fprintln(os.Stderr, "reading standard input:", err)
  343. }
  344. }
  345.  
  346. }
  347.  
Time limit exceeded #stdin #stdout 5s 3264KB
stdin
door push
knob twist
door push
stopper set
door pull
door push
door pull

knob release
door push

knob twist
door push


autocloser set
stopper set
stdout
You can input [Object] [Verbs] 
door push/pull 
knob twist/release
stopper set/release
autocloser set
monkey !
>>door,push
Door try to open,but failed
stopper don't recognize doorOpenFail
>>knob,twist
knob twisted
latch open
Door Open UnLocked
>>door,push
****Door open!!
stopper unlock
Door Close UnLocked
>>stopper,set
stopper lock
Door Close Locked
>>door,pull
Door try to close,but failed
stopper don't recognize doorCloseFail
>>door,push
Door already open
stopper unlock
Door Close UnLocked
>>door,pull
****Door Close!!
stopper don't recognize doorClose
>>knob,release
knob untwisted
latch lock
Door Open Locked
>>door,push
Door try to open,but failed
stopper don't recognize doorOpenFail
>>knob,twist
knob twisted
latch open
Door Open UnLocked
>>door,push
****Door open!!
stopper unlock
Door Close UnLocked
>>autocloser,set
3
>>stopper,set
stopper lock
Door Close Locked
2
1
autocloser pulls door
Door try to close,but failed
stopper don't recognize doorCloseFail