oh-my-oop 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.
Files changed (660) hide show
  1. package/MCP_STRUCTURE.md +301 -0
  2. package/README.md +167 -0
  3. package/SCOPE.md +27 -0
  4. package/dist/application/discovery.d.ts +133 -0
  5. package/dist/application/discovery.js +62 -0
  6. package/dist/application/discovery.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +80 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +16 -0
  11. package/dist/config.js +32 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/domain/collaborators.d.ts +2 -0
  14. package/dist/domain/collaborators.js +26 -0
  15. package/dist/domain/collaborators.js.map +1 -0
  16. package/dist/domain/ids.d.ts +4 -0
  17. package/dist/domain/ids.js +23 -0
  18. package/dist/domain/ids.js.map +1 -0
  19. package/dist/domain/model.d.ts +71 -0
  20. package/dist/domain/model.js +2 -0
  21. package/dist/domain/model.js.map +1 -0
  22. package/dist/domain/schemas.d.ts +213 -0
  23. package/dist/domain/schemas.js +79 -0
  24. package/dist/domain/schemas.js.map +1 -0
  25. package/dist/domain/stereotypes.d.ts +7 -0
  26. package/dist/domain/stereotypes.js +65 -0
  27. package/dist/domain/stereotypes.js.map +1 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +21 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/io/classStore.d.ts +9 -0
  32. package/dist/io/classStore.js +39 -0
  33. package/dist/io/classStore.js.map +1 -0
  34. package/dist/io/collaborationStore.d.ts +7 -0
  35. package/dist/io/collaborationStore.js +32 -0
  36. package/dist/io/collaborationStore.js.map +1 -0
  37. package/dist/io/design.d.ts +3 -0
  38. package/dist/io/design.js +22 -0
  39. package/dist/io/design.js.map +1 -0
  40. package/dist/io/designIndex.d.ts +6 -0
  41. package/dist/io/designIndex.js +49 -0
  42. package/dist/io/designIndex.js.map +1 -0
  43. package/dist/io/frontmatter.d.ts +8 -0
  44. package/dist/io/frontmatter.js +31 -0
  45. package/dist/io/frontmatter.js.map +1 -0
  46. package/dist/io/history.d.ts +10 -0
  47. package/dist/io/history.js +38 -0
  48. package/dist/io/history.js.map +1 -0
  49. package/dist/io/useCaseStore.d.ts +8 -0
  50. package/dist/io/useCaseStore.js +36 -0
  51. package/dist/io/useCaseStore.js.map +1 -0
  52. package/dist/io/workspace.d.ts +14 -0
  53. package/dist/io/workspace.js +82 -0
  54. package/dist/io/workspace.js.map +1 -0
  55. package/dist/oop/commands.d.ts +446 -0
  56. package/dist/oop/commands.js +319 -0
  57. package/dist/oop/commands.js.map +1 -0
  58. package/dist/oop/conformance.d.ts +16 -0
  59. package/dist/oop/conformance.js +30 -0
  60. package/dist/oop/conformance.js.map +1 -0
  61. package/dist/prompts/discovery.d.ts +2 -0
  62. package/dist/prompts/discovery.js +41 -0
  63. package/dist/prompts/discovery.js.map +1 -0
  64. package/dist/prompts/imagineWithoutController.d.ts +2 -0
  65. package/dist/prompts/imagineWithoutController.js +75 -0
  66. package/dist/prompts/imagineWithoutController.js.map +1 -0
  67. package/dist/prompts/index.d.ts +2 -0
  68. package/dist/prompts/index.js +17 -0
  69. package/dist/prompts/index.js.map +1 -0
  70. package/dist/prompts/phasePressureTest.d.ts +2 -0
  71. package/dist/prompts/phasePressureTest.js +69 -0
  72. package/dist/prompts/phasePressureTest.js.map +1 -0
  73. package/dist/prompts/rddIntro.d.ts +2 -0
  74. package/dist/prompts/rddIntro.js +53 -0
  75. package/dist/prompts/rddIntro.js.map +1 -0
  76. package/dist/prompts/review.d.ts +2 -0
  77. package/dist/prompts/review.js +45 -0
  78. package/dist/prompts/review.js.map +1 -0
  79. package/dist/prompts/stateMachineIntrospect.d.ts +2 -0
  80. package/dist/prompts/stateMachineIntrospect.js +80 -0
  81. package/dist/prompts/stateMachineIntrospect.js.map +1 -0
  82. package/dist/prompts/tellDontAskRephrase.d.ts +2 -0
  83. package/dist/prompts/tellDontAskRephrase.js +66 -0
  84. package/dist/prompts/tellDontAskRephrase.js.map +1 -0
  85. package/dist/render/diff.d.ts +21 -0
  86. package/dist/render/diff.js +84 -0
  87. package/dist/render/diff.js.map +1 -0
  88. package/dist/render/mermaid.d.ts +24 -0
  89. package/dist/render/mermaid.js +53 -0
  90. package/dist/render/mermaid.js.map +1 -0
  91. package/dist/render/sideBySide.d.ts +14 -0
  92. package/dist/render/sideBySide.js +91 -0
  93. package/dist/render/sideBySide.js.map +1 -0
  94. package/dist/resources/index.d.ts +2 -0
  95. package/dist/resources/index.js +349 -0
  96. package/dist/resources/index.js.map +1 -0
  97. package/dist/server.d.ts +2 -0
  98. package/dist/server.js +22 -0
  99. package/dist/server.js.map +1 -0
  100. package/dist/tools/alternatives.d.ts +2 -0
  101. package/dist/tools/alternatives.js +9 -0
  102. package/dist/tools/alternatives.js.map +1 -0
  103. package/dist/tools/classes.d.ts +2 -0
  104. package/dist/tools/classes.js +13 -0
  105. package/dist/tools/classes.js.map +1 -0
  106. package/dist/tools/collaborations.d.ts +2 -0
  107. package/dist/tools/collaborations.js +8 -0
  108. package/dist/tools/collaborations.js.map +1 -0
  109. package/dist/tools/compare.d.ts +2 -0
  110. package/dist/tools/compare.js +9 -0
  111. package/dist/tools/compare.js.map +1 -0
  112. package/dist/tools/conformance.d.ts +3 -0
  113. package/dist/tools/conformance.js +11 -0
  114. package/dist/tools/conformance.js.map +1 -0
  115. package/dist/tools/diagram.d.ts +2 -0
  116. package/dist/tools/diagram.js +9 -0
  117. package/dist/tools/diagram.js.map +1 -0
  118. package/dist/tools/discovery.d.ts +2 -0
  119. package/dist/tools/discovery.js +23 -0
  120. package/dist/tools/discovery.js.map +1 -0
  121. package/dist/tools/index.d.ts +2 -0
  122. package/dist/tools/index.js +27 -0
  123. package/dist/tools/index.js.map +1 -0
  124. package/dist/tools/init.d.ts +2 -0
  125. package/dist/tools/init.js +9 -0
  126. package/dist/tools/init.js.map +1 -0
  127. package/dist/tools/oop.d.ts +9 -0
  128. package/dist/tools/oop.js +26 -0
  129. package/dist/tools/oop.js.map +1 -0
  130. package/dist/tools/responsibilities.d.ts +2 -0
  131. package/dist/tools/responsibilities.js +13 -0
  132. package/dist/tools/responsibilities.js.map +1 -0
  133. package/dist/tools/state.d.ts +2 -0
  134. package/dist/tools/state.js +8 -0
  135. package/dist/tools/state.js.map +1 -0
  136. package/dist/tools/useCases.d.ts +2 -0
  137. package/dist/tools/useCases.js +18 -0
  138. package/dist/tools/useCases.js.map +1 -0
  139. package/dist/tools/validate.d.ts +2 -0
  140. package/dist/tools/validate.js +9 -0
  141. package/dist/tools/validate.js.map +1 -0
  142. package/dist/tradeoff/engine.d.ts +61 -0
  143. package/dist/tradeoff/engine.js +171 -0
  144. package/dist/tradeoff/engine.js.map +1 -0
  145. package/dist/tradeoff/heuristics/classSplit.d.ts +3 -0
  146. package/dist/tradeoff/heuristics/classSplit.js +94 -0
  147. package/dist/tradeoff/heuristics/classSplit.js.map +1 -0
  148. package/dist/tradeoff/heuristics/collaborationShape.d.ts +2 -0
  149. package/dist/tradeoff/heuristics/collaborationShape.js +82 -0
  150. package/dist/tradeoff/heuristics/collaborationShape.js.map +1 -0
  151. package/dist/tradeoff/heuristics/collectionShape.d.ts +2 -0
  152. package/dist/tradeoff/heuristics/collectionShape.js +113 -0
  153. package/dist/tradeoff/heuristics/collectionShape.js.map +1 -0
  154. package/dist/tradeoff/heuristics/dualSubjectComparison.d.ts +2 -0
  155. package/dist/tradeoff/heuristics/dualSubjectComparison.js +114 -0
  156. package/dist/tradeoff/heuristics/dualSubjectComparison.js.map +1 -0
  157. package/dist/tradeoff/heuristics/errorHandling.d.ts +2 -0
  158. package/dist/tradeoff/heuristics/errorHandling.js +110 -0
  159. package/dist/tradeoff/heuristics/errorHandling.js.map +1 -0
  160. package/dist/tradeoff/heuristics/responsibilitySplit.d.ts +23 -0
  161. package/dist/tradeoff/heuristics/responsibilitySplit.js +183 -0
  162. package/dist/tradeoff/heuristics/responsibilitySplit.js.map +1 -0
  163. package/dist/tradeoff/heuristics/stereotypeChoice.d.ts +2 -0
  164. package/dist/tradeoff/heuristics/stereotypeChoice.js +23 -0
  165. package/dist/tradeoff/heuristics/stereotypeChoice.js.map +1 -0
  166. package/dist/tradeoff/heuristics/strategyOrPolicy.d.ts +2 -0
  167. package/dist/tradeoff/heuristics/strategyOrPolicy.js +110 -0
  168. package/dist/tradeoff/heuristics/strategyOrPolicy.js.map +1 -0
  169. package/dist/tradeoff/heuristics/valueObjectShape.d.ts +2 -0
  170. package/dist/tradeoff/heuristics/valueObjectShape.js +111 -0
  171. package/dist/tradeoff/heuristics/valueObjectShape.js.map +1 -0
  172. package/dist/tradeoff/templates.d.ts +2 -0
  173. package/dist/tradeoff/templates.js +33 -0
  174. package/dist/tradeoff/templates.js.map +1 -0
  175. package/dist/util/log.d.ts +1 -0
  176. package/dist/util/log.js +7 -0
  177. package/dist/util/log.js.map +1 -0
  178. package/dist/util/mcp.d.ts +4 -0
  179. package/dist/util/mcp.js +18 -0
  180. package/dist/util/mcp.js.map +1 -0
  181. package/dist/validate/cohesion.d.ts +3 -0
  182. package/dist/validate/cohesion.js +88 -0
  183. package/dist/validate/cohesion.js.map +1 -0
  184. package/dist/validate/collectionWrapper.d.ts +3 -0
  185. package/dist/validate/collectionWrapper.js +131 -0
  186. package/dist/validate/collectionWrapper.js.map +1 -0
  187. package/dist/validate/coupling.d.ts +3 -0
  188. package/dist/validate/coupling.js +47 -0
  189. package/dist/validate/coupling.js.map +1 -0
  190. package/dist/validate/cycle.d.ts +3 -0
  191. package/dist/validate/cycle.js +101 -0
  192. package/dist/validate/cycle.js.map +1 -0
  193. package/dist/validate/dataDuplication.d.ts +3 -0
  194. package/dist/validate/dataDuplication.js +150 -0
  195. package/dist/validate/dataDuplication.js.map +1 -0
  196. package/dist/validate/dependencyDirection.d.ts +3 -0
  197. package/dist/validate/dependencyDirection.js +106 -0
  198. package/dist/validate/dependencyDirection.js.map +1 -0
  199. package/dist/validate/dualUseKnowing.d.ts +3 -0
  200. package/dist/validate/dualUseKnowing.js +137 -0
  201. package/dist/validate/dualUseKnowing.js.map +1 -0
  202. package/dist/validate/emptyObjectFill.d.ts +3 -0
  203. package/dist/validate/emptyObjectFill.js +119 -0
  204. package/dist/validate/emptyObjectFill.js.map +1 -0
  205. package/dist/validate/findings.d.ts +22 -0
  206. package/dist/validate/findings.js +12 -0
  207. package/dist/validate/findings.js.map +1 -0
  208. package/dist/validate/functionDecompositionExcess.d.ts +3 -0
  209. package/dist/validate/functionDecompositionExcess.js +120 -0
  210. package/dist/validate/functionDecompositionExcess.js.map +1 -0
  211. package/dist/validate/functionNotObject.d.ts +3 -0
  212. package/dist/validate/functionNotObject.js +80 -0
  213. package/dist/validate/functionNotObject.js.map +1 -0
  214. package/dist/validate/godObject.d.ts +6 -0
  215. package/dist/validate/godObject.js +76 -0
  216. package/dist/validate/godObject.js.map +1 -0
  217. package/dist/validate/presentationInDomain.d.ts +3 -0
  218. package/dist/validate/presentationInDomain.js +57 -0
  219. package/dist/validate/presentationInDomain.js.map +1 -0
  220. package/dist/validate/primitiveWrapper.d.ts +3 -0
  221. package/dist/validate/primitiveWrapper.js +106 -0
  222. package/dist/validate/primitiveWrapper.js.map +1 -0
  223. package/dist/validate/rules.d.ts +24 -0
  224. package/dist/validate/rules.js +269 -0
  225. package/dist/validate/rules.js.map +1 -0
  226. package/dist/validate/singletonStatefulHolder.d.ts +3 -0
  227. package/dist/validate/singletonStatefulHolder.js +128 -0
  228. package/dist/validate/singletonStatefulHolder.js.map +1 -0
  229. package/dist/validate/strategyAsymmetry.d.ts +3 -0
  230. package/dist/validate/strategyAsymmetry.js +131 -0
  231. package/dist/validate/strategyAsymmetry.js.map +1 -0
  232. package/dist/validate/testability.d.ts +5 -0
  233. package/dist/validate/testability.js +157 -0
  234. package/dist/validate/testability.js.map +1 -0
  235. package/dist/validate/vagueName.d.ts +3 -0
  236. package/dist/validate/vagueName.js +136 -0
  237. package/dist/validate/vagueName.js.map +1 -0
  238. package/dist/validate/validationLocation.d.ts +3 -0
  239. package/dist/validate/validationLocation.js +120 -0
  240. package/dist/validate/validationLocation.js.map +1 -0
  241. package/lessons/STYLE_GUIDE.md +304 -0
  242. package/lessons/woowacourse-kotlin-blackjack/2chang5/33-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +293 -0
  243. package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/52-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +106 -0
  244. package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/9-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
  245. package/lessons/woowacourse-kotlin-blackjack/DYGames/14-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +182 -0
  246. package/lessons/woowacourse-kotlin-blackjack/DYGames/37-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +122 -0
  247. package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/12-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +117 -0
  248. package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/38-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +291 -0
  249. package/lessons/woowacourse-kotlin-blackjack/HANDOVER.md +1475 -0
  250. package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/119-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +251 -0
  251. package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/137-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +459 -0
  252. package/lessons/woowacourse-kotlin-blackjack/Hevton/100-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
  253. package/lessons/woowacourse-kotlin-blackjack/Hevton/82-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +303 -0
  254. package/lessons/woowacourse-kotlin-blackjack/Hogu59/71-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +134 -0
  255. package/lessons/woowacourse-kotlin-blackjack/Hogu59/96-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +323 -0
  256. package/lessons/woowacourse-kotlin-blackjack/JoYehyun99/66-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +210 -0
  257. package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/101-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +191 -0
  258. package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/80-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  259. package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/108-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +516 -0
  260. package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/133-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +541 -0
  261. package/lessons/woowacourse-kotlin-blackjack/RightHennessy/22-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
  262. package/lessons/woowacourse-kotlin-blackjack/RightHennessy/48-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  263. package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/16-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +228 -0
  264. package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/54-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +227 -0
  265. package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/76-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  266. package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +203 -0
  267. package/lessons/woowacourse-kotlin-blackjack/aprilgom/105-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +162 -0
  268. package/lessons/woowacourse-kotlin-blackjack/aprilgom/64-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  269. package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/18-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  270. package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/36-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +769 -0
  271. package/lessons/woowacourse-kotlin-blackjack/briandr97/19-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +226 -0
  272. package/lessons/woowacourse-kotlin-blackjack/briandr97/59-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +193 -0
  273. package/lessons/woowacourse-kotlin-blackjack/chaehyuns/70-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
  274. package/lessons/woowacourse-kotlin-blackjack/chaehyuns/98-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
  275. package/lessons/woowacourse-kotlin-blackjack/chanho0908/123-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +277 -0
  276. package/lessons/woowacourse-kotlin-blackjack/chanho0908/150-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
  277. package/lessons/woowacourse-kotlin-blackjack/chws0508/26-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +259 -0
  278. package/lessons/woowacourse-kotlin-blackjack/chws0508/43-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +189 -0
  279. package/lessons/woowacourse-kotlin-blackjack/cucumber99/109-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +351 -0
  280. package/lessons/woowacourse-kotlin-blackjack/cucumber99/149-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +147 -0
  281. package/lessons/woowacourse-kotlin-blackjack/devfeijoa/121-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +168 -0
  282. package/lessons/woowacourse-kotlin-blackjack/devfeijoa/153-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +116 -0
  283. package/lessons/woowacourse-kotlin-blackjack/doabletuple/126-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +680 -0
  284. package/lessons/woowacourse-kotlin-blackjack/doabletuple/142-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +739 -0
  285. package/lessons/woowacourse-kotlin-blackjack/donghyun81/116-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
  286. package/lessons/woowacourse-kotlin-blackjack/donghyun81/147-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +244 -0
  287. package/lessons/woowacourse-kotlin-blackjack/dpcks0509/78-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +232 -0
  288. package/lessons/woowacourse-kotlin-blackjack/dpcks0509/88-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +137 -0
  289. package/lessons/woowacourse-kotlin-blackjack/etama123/112-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
  290. package/lessons/woowacourse-kotlin-blackjack/etama123/148-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +240 -0
  291. package/lessons/woowacourse-kotlin-blackjack/gaeun5744/102-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +146 -0
  292. package/lessons/woowacourse-kotlin-blackjack/gaeun5744/69-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
  293. package/lessons/woowacourse-kotlin-blackjack/gahyunkim/118-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +397 -0
  294. package/lessons/woowacourse-kotlin-blackjack/gahyunkim/141-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +215 -0
  295. package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/106-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +395 -0
  296. package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/134-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
  297. package/lessons/woowacourse-kotlin-blackjack/haeum808/62-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +230 -0
  298. package/lessons/woowacourse-kotlin-blackjack/haeum808/89-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +169 -0
  299. package/lessons/woowacourse-kotlin-blackjack/hwannow/110-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
  300. package/lessons/woowacourse-kotlin-blackjack/hwannow/132-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +573 -0
  301. package/lessons/woowacourse-kotlin-blackjack/hxeyexn/103-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  302. package/lessons/woowacourse-kotlin-blackjack/hxeyexn/81-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +301 -0
  303. package/lessons/woowacourse-kotlin-blackjack/hyemdooly/21-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +613 -0
  304. package/lessons/woowacourse-kotlin-blackjack/hyemdooly/35-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +691 -0
  305. package/lessons/woowacourse-kotlin-blackjack/hyunji1203/13-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
  306. package/lessons/woowacourse-kotlin-blackjack/ii2001/79-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +153 -0
  307. package/lessons/woowacourse-kotlin-blackjack/ii2001/85-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +318 -0
  308. package/lessons/woowacourse-kotlin-blackjack/ijh1298/128-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
  309. package/lessons/woowacourse-kotlin-blackjack/ijh1298/135-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
  310. package/lessons/woowacourse-kotlin-blackjack/inseonyun/28-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +346 -0
  311. package/lessons/woowacourse-kotlin-blackjack/inseonyun/49-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +360 -0
  312. package/lessons/woowacourse-kotlin-blackjack/ippnsj/30-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +152 -0
  313. package/lessons/woowacourse-kotlin-blackjack/ippnsj/42-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +213 -0
  314. package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/73-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +247 -0
  315. package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/87-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +900 -0
  316. package/lessons/woowacourse-kotlin-blackjack/jerry8282/125-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +248 -0
  317. package/lessons/woowacourse-kotlin-blackjack/jerry8282/151-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +243 -0
  318. package/lessons/woowacourse-kotlin-blackjack/jinuemong/63-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +281 -0
  319. package/lessons/woowacourse-kotlin-blackjack/jinuemong/92-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +283 -0
  320. package/lessons/woowacourse-kotlin-blackjack/jiyuneel/113-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +348 -0
  321. package/lessons/woowacourse-kotlin-blackjack/jiyuneel/140-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
  322. package/lessons/woowacourse-kotlin-blackjack/junjange/61-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +270 -0
  323. package/lessons/woowacourse-kotlin-blackjack/junjange/93-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +465 -0
  324. package/lessons/woowacourse-kotlin-blackjack/junseo511/107-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +296 -0
  325. package/lessons/woowacourse-kotlin-blackjack/junseo511/145-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +316 -0
  326. package/lessons/woowacourse-kotlin-blackjack/ki960213/11-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
  327. package/lessons/woowacourse-kotlin-blackjack/kimhm0728/72-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +458 -0
  328. package/lessons/woowacourse-kotlin-blackjack/kimhm0728/97-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +225 -0
  329. package/lessons/woowacourse-kotlin-blackjack/kkosang/68-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
  330. package/lessons/woowacourse-kotlin-blackjack/kkosang/94-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +158 -0
  331. package/lessons/woowacourse-kotlin-blackjack/kmkim2689/65-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +252 -0
  332. package/lessons/woowacourse-kotlin-blackjack/kmkim2689/90-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +460 -0
  333. package/lessons/woowacourse-kotlin-blackjack/krrong/32-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
  334. package/lessons/woowacourse-kotlin-blackjack/krrong/46-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +285 -0
  335. package/lessons/woowacourse-kotlin-blackjack/m6z1/122-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +177 -0
  336. package/lessons/woowacourse-kotlin-blackjack/m6z1/144-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +155 -0
  337. package/lessons/woowacourse-kotlin-blackjack/medAndro/130-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
  338. package/lessons/woowacourse-kotlin-blackjack/medAndro/143-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +678 -0
  339. package/lessons/woowacourse-kotlin-blackjack/moondev03/114-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +262 -0
  340. package/lessons/woowacourse-kotlin-blackjack/moondev03/131-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +498 -0
  341. package/lessons/woowacourse-kotlin-blackjack/murjune/77-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +287 -0
  342. package/lessons/woowacourse-kotlin-blackjack/murjune/91-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +280 -0
  343. package/lessons/woowacourse-kotlin-blackjack/no1msh/31-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
  344. package/lessons/woowacourse-kotlin-blackjack/otter66/24-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +302 -0
  345. package/lessons/woowacourse-kotlin-blackjack/otter66/58-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +391 -0
  346. package/lessons/woowacourse-kotlin-blackjack/oungsi2000/111-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  347. package/lessons/woowacourse-kotlin-blackjack/oungsi2000/136-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +540 -0
  348. package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/117-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +819 -0
  349. package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/139-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
  350. package/lessons/woowacourse-kotlin-blackjack/pingu244/20-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +258 -0
  351. package/lessons/woowacourse-kotlin-blackjack/pingu244/41-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +171 -0
  352. package/lessons/woowacourse-kotlin-blackjack/re4rk/34-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +289 -0
  353. package/lessons/woowacourse-kotlin-blackjack/re4rk/8-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
  354. package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/17-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  355. package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/50-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +145 -0
  356. package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/23-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  357. package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/39-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
  358. package/lessons/woowacourse-kotlin-blackjack/rosemin928/129-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +726 -0
  359. package/lessons/woowacourse-kotlin-blackjack/rosemin928/138-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +845 -0
  360. package/lessons/woowacourse-kotlin-blackjack/s6m1n/67-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +220 -0
  361. package/lessons/woowacourse-kotlin-blackjack/s6m1n/99-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +229 -0
  362. package/lessons/woowacourse-kotlin-blackjack/s9hn/10-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +284 -0
  363. package/lessons/woowacourse-kotlin-blackjack/sh1mj1/75-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
  364. package/lessons/woowacourse-kotlin-blackjack/songpink/74-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
  365. package/lessons/woowacourse-kotlin-blackjack/songpink/95-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
  366. package/lessons/woowacourse-kotlin-blackjack/sujin9/15-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +132 -0
  367. package/lessons/woowacourse-kotlin-blackjack/sujin9/47-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
  368. package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/29-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
  369. package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/51-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
  370. package/lessons/woowacourse-kotlin-blackjack/tobae-time/115-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
  371. package/lessons/woowacourse-kotlin-blackjack/tobae-time/154-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +298 -0
  372. package/lessons/woowacourse-kotlin-blackjack/whk06061/25-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +235 -0
  373. package/lessons/woowacourse-kotlin-blackjack/whk06061/53-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +130 -0
  374. package/lessons/woowacourse-kotlin-blackjack/wondroid-world/124-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +486 -0
  375. package/lessons/woowacourse-kotlin-blackjack/wondroid-world/152-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +482 -0
  376. package/lessons/woowacourse-kotlin-blackjack/yrsel/120-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +194 -0
  377. package/lessons/woowacourse-kotlin-blackjack/yrsel/146-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +444 -0
  378. package/lessons/woowacourse-kotlin-lotto/2chang5/27-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  379. package/lessons/woowacourse-kotlin-lotto/2chang5/52-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +187 -0
  380. package/lessons/woowacourse-kotlin-lotto/Choisehyeon/14-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +206 -0
  381. package/lessons/woowacourse-kotlin-lotto/Choisehyeon/47-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
  382. package/lessons/woowacourse-kotlin-lotto/DYGames/2-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
  383. package/lessons/woowacourse-kotlin-lotto/DYGames/34-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +88 -0
  384. package/lessons/woowacourse-kotlin-lotto/EmilyCh0/12-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  385. package/lessons/woowacourse-kotlin-lotto/EmilyCh0/40-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +135 -0
  386. package/lessons/woowacourse-kotlin-lotto/HANDOVER.md +217 -0
  387. package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/121-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  388. package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/139-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +75 -0
  389. package/lessons/woowacourse-kotlin-lotto/Hevton/76-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  390. package/lessons/woowacourse-kotlin-lotto/Hevton/92-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +122 -0
  391. package/lessons/woowacourse-kotlin-lotto/Hogu59/100-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +110 -0
  392. package/lessons/woowacourse-kotlin-lotto/Hogu59/68-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +84 -0
  393. package/lessons/woowacourse-kotlin-lotto/JoYehyun99/60-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
  394. package/lessons/woowacourse-kotlin-lotto/JoYehyun99/96-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
  395. package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/61-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  396. package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/93-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +16 -0
  397. package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/109-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +57 -0
  398. package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/135-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
  399. package/lessons/woowacourse-kotlin-lotto/PROGRESS.md +160 -0
  400. package/lessons/woowacourse-kotlin-lotto/README.md +77 -0
  401. package/lessons/woowacourse-kotlin-lotto/RightHennessy/32-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  402. package/lessons/woowacourse-kotlin-lotto/RightHennessy/5-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  403. package/lessons/woowacourse-kotlin-lotto/SUMMARY.md +369 -0
  404. package/lessons/woowacourse-kotlin-lotto/SeongHoonC/25-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  405. package/lessons/woowacourse-kotlin-lotto/SeongHoonC/37-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +27 -0
  406. package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/72-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +137 -0
  407. package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +17 -0
  408. package/lessons/woowacourse-kotlin-lotto/aprilgom/102-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +62 -0
  409. package/lessons/woowacourse-kotlin-lotto/aprilgom/64-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
  410. package/lessons/woowacourse-kotlin-lotto/boogi-woogi/11-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  411. package/lessons/woowacourse-kotlin-lotto/boogi-woogi/29-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  412. package/lessons/woowacourse-kotlin-lotto/briandr97/26-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  413. package/lessons/woowacourse-kotlin-lotto/briandr97/51-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +123 -0
  414. package/lessons/woowacourse-kotlin-lotto/chaehyuns/71-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
  415. package/lessons/woowacourse-kotlin-lotto/chaehyuns/97-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  416. package/lessons/woowacourse-kotlin-lotto/chanho0908/124-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
  417. package/lessons/woowacourse-kotlin-lotto/chanho0908/129-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  418. package/lessons/woowacourse-kotlin-lotto/chws0508/24-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +117 -0
  419. package/lessons/woowacourse-kotlin-lotto/chws0508/50-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +167 -0
  420. package/lessons/woowacourse-kotlin-lotto/cucumber99/116-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  421. package/lessons/woowacourse-kotlin-lotto/cucumber99/147-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +223 -0
  422. package/lessons/woowacourse-kotlin-lotto/devfeijoa/125-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
  423. package/lessons/woowacourse-kotlin-lotto/devfeijoa/153-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  424. package/lessons/woowacourse-kotlin-lotto/doabletuple/119-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
  425. package/lessons/woowacourse-kotlin-lotto/doabletuple/138-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +77 -0
  426. package/lessons/woowacourse-kotlin-lotto/donghyun81/111-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
  427. package/lessons/woowacourse-kotlin-lotto/donghyun81/152-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  428. package/lessons/woowacourse-kotlin-lotto/dpcks0509/80-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
  429. package/lessons/woowacourse-kotlin-lotto/dpcks0509/87-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +134 -0
  430. package/lessons/woowacourse-kotlin-lotto/etama123/112-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +170 -0
  431. package/lessons/woowacourse-kotlin-lotto/etama123/148-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +183 -0
  432. package/lessons/woowacourse-kotlin-lotto/gaeun5744/101-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  433. package/lessons/woowacourse-kotlin-lotto/gaeun5744/78-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
  434. package/lessons/woowacourse-kotlin-lotto/gahyunkim/107-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
  435. package/lessons/woowacourse-kotlin-lotto/gahyunkim/136-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
  436. package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/106-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
  437. package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/137-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +111 -0
  438. package/lessons/woowacourse-kotlin-lotto/haeum808/67-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  439. package/lessons/woowacourse-kotlin-lotto/haeum808/95-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  440. package/lessons/woowacourse-kotlin-lotto/hwannow/113-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +235 -0
  441. package/lessons/woowacourse-kotlin-lotto/hwannow/132-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  442. package/lessons/woowacourse-kotlin-lotto/hxeyexn/77-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
  443. package/lessons/woowacourse-kotlin-lotto/hxeyexn/98-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +162 -0
  444. package/lessons/woowacourse-kotlin-lotto/hyemdooly/17-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
  445. package/lessons/woowacourse-kotlin-lotto/hyemdooly/28-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +23 -0
  446. package/lessons/woowacourse-kotlin-lotto/hyunji1203/15-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
  447. package/lessons/woowacourse-kotlin-lotto/hyunji1203/48-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
  448. package/lessons/woowacourse-kotlin-lotto/ii2001/62-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  449. package/lessons/woowacourse-kotlin-lotto/ii2001/88-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  450. package/lessons/woowacourse-kotlin-lotto/ijh1298/122-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
  451. package/lessons/woowacourse-kotlin-lotto/ijh1298/133-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
  452. package/lessons/woowacourse-kotlin-lotto/inseonyun/3-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +222 -0
  453. package/lessons/woowacourse-kotlin-lotto/inseonyun/49-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +166 -0
  454. package/lessons/woowacourse-kotlin-lotto/ippnsj/16-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +154 -0
  455. package/lessons/woowacourse-kotlin-lotto/ippnsj/55-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  456. package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/59-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
  457. package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/83-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +53 -0
  458. package/lessons/woowacourse-kotlin-lotto/jerry8282/115-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  459. package/lessons/woowacourse-kotlin-lotto/jerry8282/134-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  460. package/lessons/woowacourse-kotlin-lotto/jinuemong/63-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +144 -0
  461. package/lessons/woowacourse-kotlin-lotto/jinuemong/89-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
  462. package/lessons/woowacourse-kotlin-lotto/jiyuneel/128-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  463. package/lessons/woowacourse-kotlin-lotto/jiyuneel/144-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  464. package/lessons/woowacourse-kotlin-lotto/junjange/58-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
  465. package/lessons/woowacourse-kotlin-lotto/junjange/81-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  466. package/lessons/woowacourse-kotlin-lotto/junseo511/120-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
  467. package/lessons/woowacourse-kotlin-lotto/junseo511/131-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +188 -0
  468. package/lessons/woowacourse-kotlin-lotto/ki960213/43-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +24 -0
  469. package/lessons/woowacourse-kotlin-lotto/ki960213/8-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +159 -0
  470. package/lessons/woowacourse-kotlin-lotto/kimhm0728/74-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +50 -0
  471. package/lessons/woowacourse-kotlin-lotto/kimhm0728/94-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
  472. package/lessons/woowacourse-kotlin-lotto/kkosang/85-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  473. package/lessons/woowacourse-kotlin-lotto/kmkim2689/70-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  474. package/lessons/woowacourse-kotlin-lotto/kmkim2689/82-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
  475. package/lessons/woowacourse-kotlin-lotto/krrong/19-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +161 -0
  476. package/lessons/woowacourse-kotlin-lotto/krrong/41-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +73 -0
  477. package/lessons/woowacourse-kotlin-lotto/m6z1/105-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
  478. package/lessons/woowacourse-kotlin-lotto/m6z1/151-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  479. package/lessons/woowacourse-kotlin-lotto/medAndro/127-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +186 -0
  480. package/lessons/woowacourse-kotlin-lotto/medAndro/130-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +132 -0
  481. package/lessons/woowacourse-kotlin-lotto/moondev03/110-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  482. package/lessons/woowacourse-kotlin-lotto/moondev03/141-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  483. package/lessons/woowacourse-kotlin-lotto/murjune/69-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  484. package/lessons/woowacourse-kotlin-lotto/murjune/90-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +177 -0
  485. package/lessons/woowacourse-kotlin-lotto/no1msh/20-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +69 -0
  486. package/lessons/woowacourse-kotlin-lotto/no1msh/46-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  487. package/lessons/woowacourse-kotlin-lotto/otter66/13-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  488. package/lessons/woowacourse-kotlin-lotto/otter66/53-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +160 -0
  489. package/lessons/woowacourse-kotlin-lotto/oungsi2000/126-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
  490. package/lessons/woowacourse-kotlin-lotto/oungsi2000/149-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +56 -0
  491. package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/117-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  492. package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/146-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +173 -0
  493. package/lessons/woowacourse-kotlin-lotto/pingu244/33-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  494. package/lessons/woowacourse-kotlin-lotto/pingu244/54-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
  495. package/lessons/woowacourse-kotlin-lotto/pingu244/7-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
  496. package/lessons/woowacourse-kotlin-lotto/re4rk/31-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  497. package/lessons/woowacourse-kotlin-lotto/re4rk/4-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  498. package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/23-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  499. package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/38-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  500. package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/21-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
  501. package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/36-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
  502. package/lessons/woowacourse-kotlin-lotto/rosemin928/123-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
  503. package/lessons/woowacourse-kotlin-lotto/rosemin928/140-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +126 -0
  504. package/lessons/woowacourse-kotlin-lotto/s6m1n/103-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
  505. package/lessons/woowacourse-kotlin-lotto/s6m1n/66-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +118 -0
  506. package/lessons/woowacourse-kotlin-lotto/s9hn/18-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +112 -0
  507. package/lessons/woowacourse-kotlin-lotto/sh1mj1/75-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  508. package/lessons/woowacourse-kotlin-lotto/sh1mj1/91-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +140 -0
  509. package/lessons/woowacourse-kotlin-lotto/songpink/65-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +96 -0
  510. package/lessons/woowacourse-kotlin-lotto/songpink/99-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +64 -0
  511. package/lessons/woowacourse-kotlin-lotto/sujin9/10-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  512. package/lessons/woowacourse-kotlin-lotto/sujin9/35-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  513. package/lessons/woowacourse-kotlin-lotto/tmdgh1592/22-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
  514. package/lessons/woowacourse-kotlin-lotto/tmdgh1592/30-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  515. package/lessons/woowacourse-kotlin-lotto/tobae-time/114-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
  516. package/lessons/woowacourse-kotlin-lotto/tobae-time/145-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +120 -0
  517. package/lessons/woowacourse-kotlin-lotto/whk06061/42-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  518. package/lessons/woowacourse-kotlin-lotto/whk06061/9-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +89 -0
  519. package/lessons/woowacourse-kotlin-lotto/wondroid-world/118-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +100 -0
  520. package/lessons/woowacourse-kotlin-lotto/wondroid-world/150-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +142 -0
  521. package/lessons/woowacourse-kotlin-lotto/yrsel/108-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  522. package/lessons/woowacourse-kotlin-lotto/yrsel/143-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +108 -0
  523. package/lessons/woowacourse-racingcar/2chang5/33-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  524. package/lessons/woowacourse-racingcar/2chang5/75-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  525. package/lessons/woowacourse-racingcar/CFalws/85-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  526. package/lessons/woowacourse-racingcar/Choisehyeon/46-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  527. package/lessons/woowacourse-racingcar/DYGames/49-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  528. package/lessons/woowacourse-racingcar/EmilyCh0/40-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +64 -0
  529. package/lessons/woowacourse-racingcar/EmilyCh0/57-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  530. package/lessons/woowacourse-racingcar/HamBeomJoon/137-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  531. package/lessons/woowacourse-racingcar/HamBeomJoon/170-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  532. package/lessons/woowacourse-racingcar/Hevton/106-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  533. package/lessons/woowacourse-racingcar/Hevton/118-/353/246/254/355/214/251/355/204/260/353/247/201.md +51 -0
  534. package/lessons/woowacourse-racingcar/Hogu59/108-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  535. package/lessons/woowacourse-racingcar/Hogu59/125-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  536. package/lessons/woowacourse-racingcar/JoYehyun99/111-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  537. package/lessons/woowacourse-racingcar/JoYehyun99/88-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
  538. package/lessons/woowacourse-racingcar/Junyoung-WON/127-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  539. package/lessons/woowacourse-racingcar/Junyoung-WON/90-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  540. package/lessons/woowacourse-racingcar/Leeyerin0210/133-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  541. package/lessons/woowacourse-racingcar/Leeyerin0210/159-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  542. package/lessons/woowacourse-racingcar/PROGRESS.md +94 -0
  543. package/lessons/woowacourse-racingcar/README.md +69 -0
  544. package/lessons/woowacourse-racingcar/RightHennessy/51-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  545. package/lessons/woowacourse-racingcar/RightHennessy/58-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  546. package/lessons/woowacourse-racingcar/RunaNam/81-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
  547. package/lessons/woowacourse-racingcar/SUMMARY.md +339 -0
  548. package/lessons/woowacourse-racingcar/SeongHoonC/37-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  549. package/lessons/woowacourse-racingcar/SeongHoonC/66-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  550. package/lessons/woowacourse-racingcar/Songusika/84-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  551. package/lessons/woowacourse-racingcar/Yunseok-Nam/114-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  552. package/lessons/woowacourse-racingcar/Yunseok-Nam/96-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  553. package/lessons/woowacourse-racingcar/aprilgom/130-/353/246/254/355/214/251/355/204/260/353/247/201.md +52 -0
  554. package/lessons/woowacourse-racingcar/aprilgom/97-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  555. package/lessons/woowacourse-racingcar/awesomeo184/23-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  556. package/lessons/woowacourse-racingcar/boogi-woogi/35-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  557. package/lessons/woowacourse-racingcar/boogi-woogi/59-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  558. package/lessons/woowacourse-racingcar/briandr97/54-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  559. package/lessons/woowacourse-racingcar/chaehyuns/131-/353/246/254/355/214/251/355/204/260/353/247/201.md +49 -0
  560. package/lessons/woowacourse-racingcar/chaehyuns/99-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  561. package/lessons/woowacourse-racingcar/chanho0908/147-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  562. package/lessons/woowacourse-racingcar/chanho0908/160-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  563. package/lessons/woowacourse-racingcar/chws0508/45-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  564. package/lessons/woowacourse-racingcar/chws0508/73-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
  565. package/lessons/woowacourse-racingcar/cucumber99/132-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  566. package/lessons/woowacourse-racingcar/cucumber99/177-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  567. package/lessons/woowacourse-racingcar/devfeijoa/146-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  568. package/lessons/woowacourse-racingcar/doabletuple/149-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  569. package/lessons/woowacourse-racingcar/doabletuple/175-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  570. package/lessons/woowacourse-racingcar/donghyun81/154-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  571. package/lessons/woowacourse-racingcar/dpcks0509/103-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  572. package/lessons/woowacourse-racingcar/dpcks0509/112-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  573. package/lessons/woowacourse-racingcar/drunkenhw/82-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  574. package/lessons/woowacourse-racingcar/etama123/145-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  575. package/lessons/woowacourse-racingcar/gaeun5744/124-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
  576. package/lessons/woowacourse-racingcar/gaeun5744/93-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  577. package/lessons/woowacourse-racingcar/gahyunkim/134-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  578. package/lessons/woowacourse-racingcar/gahyunkim/164-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  579. package/lessons/woowacourse-racingcar/giovannijunseokim/140-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  580. package/lessons/woowacourse-racingcar/haeum808/101-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  581. package/lessons/woowacourse-racingcar/haeum808/129-/353/246/254/355/214/251/355/204/260/353/247/201.md +46 -0
  582. package/lessons/woowacourse-racingcar/hwannow/141-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  583. package/lessons/woowacourse-racingcar/hwannow/157-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
  584. package/lessons/woowacourse-racingcar/hxeyexn/109-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  585. package/lessons/woowacourse-racingcar/hxeyexn/128-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  586. package/lessons/woowacourse-racingcar/hyemdooly/50-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  587. package/lessons/woowacourse-racingcar/hyemdooly/68-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  588. package/lessons/woowacourse-racingcar/hyunji1203/29-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  589. package/lessons/woowacourse-racingcar/hyunji1203/60-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  590. package/lessons/woowacourse-racingcar/ii2001/102-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
  591. package/lessons/woowacourse-racingcar/ii2001/122-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  592. package/lessons/woowacourse-racingcar/ijh1298/144-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  593. package/lessons/woowacourse-racingcar/injoon2019/24-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  594. package/lessons/woowacourse-racingcar/inseonyun/44-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  595. package/lessons/woowacourse-racingcar/inseonyun/76-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  596. package/lessons/woowacourse-racingcar/ippnsj/36-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  597. package/lessons/woowacourse-racingcar/ippnsj/67-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  598. package/lessons/woowacourse-racingcar/jaeyeongjo/110-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
  599. package/lessons/woowacourse-racingcar/jaeyeongjo/89-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
  600. package/lessons/woowacourse-racingcar/jinuemong/104-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  601. package/lessons/woowacourse-racingcar/jinuemong/117-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
  602. package/lessons/woowacourse-racingcar/jiyuneel/142-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  603. package/lessons/woowacourse-racingcar/junjange/113-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +41 -0
  604. package/lessons/woowacourse-racingcar/junjange/87-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
  605. package/lessons/woowacourse-racingcar/junseo511/148-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  606. package/lessons/woowacourse-racingcar/junseo511/165-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  607. package/lessons/woowacourse-racingcar/ki960213/32-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  608. package/lessons/woowacourse-racingcar/ki960213/63-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  609. package/lessons/woowacourse-racingcar/kimhm0728/100-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  610. package/lessons/woowacourse-racingcar/kimhm0728/116-/353/246/254/355/214/251/355/204/260/353/247/201.md +54 -0
  611. package/lessons/woowacourse-racingcar/kkosang/105-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  612. package/lessons/woowacourse-racingcar/kkosang/126-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
  613. package/lessons/woowacourse-racingcar/kmkim2689/123-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  614. package/lessons/woowacourse-racingcar/kmkim2689/92-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  615. package/lessons/woowacourse-racingcar/krrong/34-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +63 -0
  616. package/lessons/woowacourse-racingcar/m6z1/150-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  617. package/lessons/woowacourse-racingcar/m6z1/156-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +40 -0
  618. package/lessons/woowacourse-racingcar/medAndro/153-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  619. package/lessons/woowacourse-racingcar/moondev03/135-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  620. package/lessons/woowacourse-racingcar/moondev03/161-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  621. package/lessons/woowacourse-racingcar/murjune/121-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  622. package/lessons/woowacourse-racingcar/murjune/95-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  623. package/lessons/woowacourse-racingcar/no1msh/43-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  624. package/lessons/woowacourse-racingcar/no1msh/69-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  625. package/lessons/woowacourse-racingcar/otter66/48-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  626. package/lessons/woowacourse-racingcar/otter66/77-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  627. package/lessons/woowacourse-racingcar/oungsi2000/152-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  628. package/lessons/woowacourse-racingcar/oungsi2000/187-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  629. package/lessons/woowacourse-racingcar/parkjiminnnn/143-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  630. package/lessons/woowacourse-racingcar/parkjiminnnn/158-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  631. package/lessons/woowacourse-racingcar/pingu244/38-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  632. package/lessons/woowacourse-racingcar/pingu244/62-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  633. package/lessons/woowacourse-racingcar/re4rk/28-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  634. package/lessons/woowacourse-racingcar/re4rk/55-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  635. package/lessons/woowacourse-racingcar/rhkrwngud445/42-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  636. package/lessons/woowacourse-racingcar/rhkrwngud445/74-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
  637. package/lessons/woowacourse-racingcar/rhthrhrl0/31-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  638. package/lessons/woowacourse-racingcar/rosemin928/138-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  639. package/lessons/woowacourse-racingcar/rosemin928/171-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +38 -0
  640. package/lessons/woowacourse-racingcar/s6m1n/120-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  641. package/lessons/woowacourse-racingcar/s6m1n/91-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  642. package/lessons/woowacourse-racingcar/s9hn/53-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
  643. package/lessons/woowacourse-racingcar/s9hn/78-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  644. package/lessons/woowacourse-racingcar/sh1mj1/107-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  645. package/lessons/woowacourse-racingcar/sh1mj1/115-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  646. package/lessons/woowacourse-racingcar/songpink/119-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  647. package/lessons/woowacourse-racingcar/songpink/98-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  648. package/lessons/woowacourse-racingcar/sujin9/52-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  649. package/lessons/woowacourse-racingcar/sujin9/61-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
  650. package/lessons/woowacourse-racingcar/tmdgh1592/47-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  651. package/lessons/woowacourse-racingcar/tmdgh1592/64-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  652. package/lessons/woowacourse-racingcar/tobae-time/151-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  653. package/lessons/woowacourse-racingcar/tobae-time/167-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  654. package/lessons/woowacourse-racingcar/whk06061/41-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  655. package/lessons/woowacourse-racingcar/wondroid-world/136-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  656. package/lessons/woowacourse-racingcar/wondroid-world/166-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  657. package/lessons/woowacourse-racingcar/yrsel/139-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  658. package/lessons/woowacourse-racingcar/yujamint/83-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  659. package/package.json +46 -0
  660. package/skills/oh-my-oop/SKILL.md +39 -0
@@ -0,0 +1,145 @@
1
+ # PR #85 — [로또] 꼬상 2단계 미션 제출합니다
2
+
3
+ - **Reviewee:** [@kkosang](https://github.com/kkosang)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/85
5
+ - **단계:** 2단계 (수동 로또 추가)
6
+ - **리뷰어:** @Gyuil-Hwnag
7
+ - **라인 코멘트:** 132 (가장 많은 코멘트)
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`LottoNumber` 값 객체 도입** — 원시 강박 탈출 (1단계 → 2단계 리팩토링의 핵심).
12
+ - **`Rank` enum** — 등수 + 상금을 enum으로 묶음.
13
+ - **`InputValidator` object로 검증 집중** — Validation 한 곳에 모음.
14
+ - **`InputException` enum** — 에러 케이스를 enum으로 정형화.
15
+ - **`require()` 활용** — 도메인 무결성.
16
+ - **`ParameterizedTest + CsvSource`** — 케이스 풍부.
17
+
18
+ ## 못한 점 (설계 관점)
19
+
20
+ ### 1. `Buyer`가 mutable `var lottos: Lottos` 보유
21
+
22
+ ```kotlin
23
+ class Buyer(private val purchaseAmount: Int) {
24
+ val numberOfLotto: Int = calculateNumberOfLotto()
25
+ var purchasedLotto: Lottos = Lottos(emptyList()) // ⚠ 초기엔 비어있다가 나중에 채워짐
26
+ }
27
+ ```
28
+
29
+ 생성자에서 모두 채우지 않고 외부에서 `buyLottos(lottos)` 메서드를 통해 나중에 채움 → invariant ("Buyer는 구매한 로또를 가진다")가 시간차로 깨짐.
30
+
31
+ ### 2. `Controller`에 `var winningStatistics` 같은 lateinit 패턴 잔존
32
+
33
+ ```kotlin
34
+ fun run() {
35
+ val purchaseAmount = InputView.inputPurchaseAmount()
36
+ buyer = Buyer(purchaseAmount)
37
+ val numberOfManualLotto = InputView.inputPurchaseSizeOfManualLotto(purchaseAmount)
38
+ publishLottos(numberOfManualLotto) // buyer 멤버에 side-effect
39
+ val winningLotto = drawWinningLotto()
40
+ winningStatistics = makeWinningStatics(buyer.purchasedLotto, winningLotto)
41
+ displayWinningStatistics(purchaseAmount)
42
+ }
43
+ ```
44
+
45
+ `run()`이 너무 많은 단계를 직접 조율. 각 단계가 *Controller 멤버 변수*에 부수효과로 결과 저장.
46
+
47
+ ### 3. `INVALID_INPUT = -1`로 magic sentinel 값 사용
48
+
49
+ ```kotlin
50
+ private const val INVALID_INPUT = -1
51
+
52
+ fun validatePurchaseAmount(input: String): Int {
53
+ val purchaseAmount = input.toIntOrNull() ?: INVALID_INPUT // ⚠ -1을 정상 흐름에 흘림
54
+ validatePurchaseAmountRange(purchaseAmount)
55
+ return purchaseAmount
56
+ }
57
+ ```
58
+
59
+ `null`이 의미하는 "변환 실패"를 `-1`이라는 정상 정수 자리에 끼워 넣음. 호출자가 검증을 안 하면 `-1`이 그대로 도메인에 들어감.
60
+
61
+ ### 4. View 안에서 try-catch + 재귀로 재입력
62
+
63
+ ```kotlin
64
+ fun inputPurchaseSizeOfManualLotto(purchaseAmount: Int): Int {
65
+ val numberOfManualLotto = br.readLine()
66
+ return try {
67
+ InputValidator.validatePurchaseSizeOfManualLotto(numberOfManualLotto, purchaseAmount)
68
+ } catch (exception: IllegalArgumentException) {
69
+ println(exception.message)
70
+ inputPurchaseSizeOfManualLotto(purchaseAmount) // ⚠ View가 재시도 흐름까지 보유
71
+ }
72
+ }
73
+ ```
74
+
75
+ InputView가 재시도 정책을 결정 — 입력 받기 책임 초과.
76
+
77
+ ### 5. `Constant.kt` 단일 파일에 모든 상수
78
+
79
+ ```kotlin
80
+ object Constant {
81
+ // 모든 상수를 한 파일에.
82
+ }
83
+ ```
84
+
85
+ → 리뷰어 지적: "`Constant`라는 네이밍은 무엇을 담당하는 것인지 혼란을 줄 수 있다. `LottoNumberConstants` 등으로."
86
+
87
+ ### 6. `Lotto.toString()`에 표현 형식
88
+
89
+ ```kotlin
90
+ open class Lotto(val numbers: List<LottoNumber>) {
91
+ override fun toString(): String {
92
+ return numbers.map { it.number }.sorted().joinToString(", ", "[", "]")
93
+ }
94
+ }
95
+ ```
96
+
97
+ 도메인 객체가 출력 형식 (`", "`, `"["`, `"]"`)을 직접 결정 → OutputView 책임 침범.
98
+
99
+ ### 7. `WinningStatistic`가 `Pair<Rank, Int>` 보유
100
+
101
+ ```kotlin
102
+ class WinningStatistic(val result: Pair<Rank, Int>) {. }
103
+ ```
104
+
105
+ `first`/`second`가 무엇인지 모름. data class 또는 명시적 필드 필요.
106
+
107
+ ## 리뷰어 의견 요지
108
+
109
+ 리뷰어 @Gyuil-Hwnag의 핵심 가르침:
110
+
111
+ 1. **모호한 이름 = 책임 모호** — `Constant`, `WinningStatistic.result` 등 일반 어휘 회피.
112
+
113
+ 2. **try-catch + 재귀 회피** — `runCatching` 또는 `toIntOrNull() ?: return inputXxx()` 같은 코틀린 idiom.
114
+
115
+ 3. **표현 형식의 자리 = OutputView** — `joinToString(", ", "[", "]")`이 도메인에 있으면 표현 변경 시 도메인 변경.
116
+
117
+ 4. **`INVALID_INPUT = -1` 같은 sentinel 값은 위험** — null/Optional/Either 등 *타입으로 실패를 표현*.
118
+
119
+ 5. **mutable lateinit 패턴 회피** — `Buyer`가 생성 시점에 구매한 로또까지 받거나, 별도 팩토리 메서드 사용.
120
+
121
+ - **대표 인용:**
122
+ > purchasedLotto를 mutable한 변수가 아닌 초기에 생성해서 사용하는 방법도 고민해보면 좋을 것 같습니다!
123
+ >
124
+ > — @Gyuil-Hwnag on `src/main/kotlin/model/Buyer.kt`
125
+
126
+ > 자칫하면 Constant라는 네이밍은 어떤 것을 담당하는 것인지에 대해서 혼란을 줄 수도 있겠다는 생각이 듭니다. LottoNumberConstants 등으로 수정하는 것도
127
+ >
128
+ > — @Gyuil-Hwnag on `src/main/kotlin/util/Constant.kt`
129
+
130
+ > INVALID_INPUT = -1으로 지정하신 이유가 있을까요??
131
+ >
132
+ > — @Gyuil-Hwnag on `src/main/kotlin/util/InputValidator.kt`
133
+
134
+ > 해당 내용을 try-catch를 사용안하는 방법으로 수정해보는 것도 고민해보면 좋을 것 같습니다!
135
+ >
136
+ > — @Gyuil-Hwnag on `src/main/kotlin/view/InputView.kt`
137
+
138
+ ## 얻은 교훈
139
+
140
+ - **mutable lateinit 패턴 = invariant의 시간차 파괴**. 객체가 생성 시점부터 *완성된 상태*를 갖도록 설계. "나중에 채워진다"는 곧 "잠시 동안은 깨진 상태"라는 뜻.
141
+ - **sentinel 값 (`-1`, `""`)은 타입 시스템의 함정**. `null` 또는 sealed class로 *실패를 타입으로* 표현해야 호출자가 강제로 처리.
142
+ - **재시도 흐름의 자리 = Coordinator(Controller)**. View는 입력 받기만, 검증 실패 시 재시도 결정은 Controller가.
143
+ - **표현 형식은 OutputView로**. `Lotto.toString()`이 표현을 결정하면 출력 변경이 도메인 변경. lotto 미션 특히 출력 포맷 변경 잦음.
144
+ - **`Pair`는 일회용**. `WinningStatistic`처럼 영구적으로 들고 다니는 자료는 data class 또는 명시적 객체로.
145
+ - **`Constant.kt`는 god-folder**. 어떤 상수든 다 들어가 응집도 0. 의미별 분리 (`LottoConstants`, `MoneyConstants`).
@@ -0,0 +1,97 @@
1
+ # PR #70 — [로또 1단계] 케이엠
2
+
3
+ - **Reviewee:** [@kmkim2689](https://github.com/kmkim2689)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/70
5
+ - **단계:** 1단계
6
+ - **리뷰어:** @ghojeong (파이로)
7
+ - **라인 코멘트:** 20
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`Rank` enum 도입 + `(countOfMatch, winningMoney)`** — 등수/상금 한 곳.
12
+ - **`LottoNumber` `value class` + `private const val MIN/MAX` + 메시지에 *상수 참조***.
13
+ - **`fun interface LottoGenerator`** — 테스트 가능 구조.
14
+ - **`runCatching + onFailure { return retry() }`** — 재시도 흐름.
15
+ - **README에 기능 요구사항 + 명세 잘 정리**.
16
+
17
+ ## 못한 점 (설계 관점)
18
+
19
+ ### 1. `Rank.valueOf`의 *복잡한 분기*
20
+
21
+ ```kotlin
22
+ companion object {
23
+ private const val MIN_COUNT = 0
24
+ private const val MISS_MAX_THRESHOLD = 2
25
+ private val NON_BONUS_COUNTS = listOf(3, 4, 6)
26
+ fun valueOf(countOfMatch: Int, matchBonus: Boolean): Rank = when {
27
+ countOfMatch in MISS_RANGE -> MISS
28
+ countOfMatch == SECOND.countOfMatch && matchBonus -> SECOND
29
+ countOfMatch == THIRD.countOfMatch -> THIRD
30
+ countOfMatch in NON_BONUS_COUNTS -> entries.first { it.countOfMatch == countOfMatch }
31
+ else -> throw IllegalArgumentException(.)
32
+ }
33
+ }
34
+ ```
35
+
36
+ 학생 자가 정리: "Rank 객체에 대해 어디까지 책임을 부여해야 할 것인가에 대해 논의. 한 의견은 *발행된 로또와 비교까지* 부여, 다른 의견은 *상수로만 활용*. 결국 Rank라는 명사의 의미(*순위라는 정보*)에 초점을 맞추어, 상수로만 활용." 리뷰어: "이미 고민에 대해 *훌륭한 결론*. … 한눈에 각각이 무슨 값을 가지고 있는지 들어오는 Rank에 비해, Rank1이 더 많은 코드를 읽어야 하기 때문입니다."
37
+
38
+ ### 2. `runCatching + onFailure { return retry() }` — 무한 루프 + indentation 깊이
39
+
40
+ ```kotlin
41
+ private fun getPurchaseExpense(): Int =
42
+ runCatching {
43
+ lottoGameInputView.inputPurchaseExpense()
44
+ }.onFailure {
45
+ if (it is IllegalArgumentException) return getPurchaseExpense()
46
+ }.getOrThrow()
47
+ ```
48
+
49
+ 리뷰어: "runCatching을 활용해 onFailure 처리를 해주시는 점 멋집니다. 하지만 예외 처리는 근본적으로 *if-else 처리와 다를 바 없다*는 점을 명심하세요. *만약 이러한 예외가 발생한다면, 이러한 로직을 처리한다*라는 조건문입니다. 즉 위와 같은 상황에서는 *조건문이 중첩되어 indentation depth가 깊어진 것*과 동일한 상황입니다. 로직을 더 작은 단위로 쪼갤 필요가 있어 보입니다. 뿐만 아니라 *조건문이 들어갔다는 것은, 곧 테스트할 로직이 있다는 의미*. Controller에 있는 로직들을 model로 옮겨서 테스트 용이하도록." + "만약 `inputPurchaseExpense()`에서 IllegalArgumentException이 계속 발생하면 *무한 루프*를 돌아야 하나요? 언제 탈출할 수 있을지에 관해서는 *조건*을 생각하면 좋을 것 같습니다. 안드로이드 개발에서 *폰이 갑자기 뜨거워지면서 벽돌*."
50
+
51
+ ### 3. 예외 메시지가 *사용자 안내*가 아님
52
+
53
+ ```kotlin
54
+ private const val EXCEPTION_PURCHASE_EXPENSE = "로또 구매 금액은 정수여야 합니다."
55
+ ```
56
+
57
+ 리뷰어: "보통 예외상황에 따른 메시지를 사용자에게 던질 때는, *사용자가 무엇을 잘못했는지 어떻게 하면 제대로 프로그램을 사용할 수 있는지* 알려주는 게 좋습니다. 가령, *음수인 -1도 정수*입니다." — *정수 입력*만으로는 *양수 + 1000원 단위*를 의미하지 않음.
58
+
59
+ ### 4. `lottie`라는 별난 명명
60
+
61
+ ```kotlin
62
+ val lottie: List<Lotto> = purchaseLottie(purchaseExpense)
63
+ ```
64
+
65
+ 리뷰어 농담: "Lotto의 복수형이 Lottie였나요? 신기하군요." — *Lottos*가 더 자연스러움.
66
+
67
+ ### 5. `value class LottoNumber` — 학생 기준 묻기
68
+
69
+ 리뷰어: "LottoNumber에서는 value class로 해주셨는데, 케이엠 님이 *value class를 언제 써야겠다*고 생각하는 본인만의 기준이 있으시나요?" — 기준 명시화 학습 유도.
70
+
71
+ ## 리뷰어 의견 요지
72
+
73
+ - **runCatching = if-else** — *indentation depth*는 *조건문 중첩*과 같음. 로직 분리 + 테스트.
74
+ - **`return retry()`는 *무한 루프* 위험** — *탈출 조건* 또는 *최대 시도 횟수* 고려.
75
+ - **사용자 메시지 = *행동 안내*** — *정수여야 합니다*는 *너무 좁음*.
76
+ - **명사형 명명 = 자연어 따라가기** — `Lottie` → `Lottos`.
77
+ - **상수 + 메시지 = *상수 참조***로 변경 동기화.
78
+ - **value class 도입의 *기준* 명시화**.
79
+
80
+ - **대표 인용:**
81
+ > 예외 처리는 근본적으로 if-else 처리와 다를 바 없다는 점을 명심하세요. 즉 위와 같은 상황에서는 조건문이 중첩되어 indentation depth가 깊어진 것과 동일한 상황입니다.
82
+ > — @ghojeong on `src/main/kotlin/controller/LottoGameController.kt`
83
+
84
+ > 만약 `inputPurchaseExpense()`에서 IllegalArgumentException이 계속 발생하면 무한 루프를 돌아야 하나요? 안드로이드 개발에서 폰이 갑자기 뜨거워지면서 벽돌이 되는 현상.
85
+ > — @ghojeong on `src/main/kotlin/controller/LottoGameController.kt`
86
+
87
+ > 가령, 음수인 -1도 정수입니다. 안드로이드 개발자 관점에서 사용자 경험에 관련된 피드백.
88
+ > — @ghojeong on `src/main/kotlin/view/ConsoleLottoGameInputView.kt`
89
+
90
+ ## 얻은 교훈
91
+
92
+ - ***runCatching은 if-else의 다른 표현*** — indentation은 같음, 테스트 가능성도 같음.
93
+ - **재시도 = 탈출 조건 필요** — *무한 루프*는 *벽돌화 위험*.
94
+ - **사용자 메시지 = *행동 안내*** — 도메인 invariant를 *행동으로 옮길 수 있게* 표현.
95
+ - **명사형은 자연어 따라가기** — *Lottie* 같이 *별난 변형*은 *읽는 부담*.
96
+ - **상수 + 메시지 = 상수 참조** — 변경 동기화.
97
+ - **value class 도입은 *명시적 기준*** — 호출자에게 *왜 이 클래스가 value class인지* 보여야 함.
@@ -0,0 +1,157 @@
1
+ # PR #82 — [로또 2단계] 케이엠
2
+
3
+ - **Reviewee:** [@kmkim2689](https://github.com/kmkim2689)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/82
5
+ - **단계:** 2단계 (수동 로또 추가)
6
+ - **리뷰어:** @ghojeong (파이로)
7
+ - **라인 코멘트:** 19
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`fun interface LotteriesGenerator { fun generate(): List<Lotto> }`** + `AutoLotteriesGenerator`/`ManualLotteriesGenerator` 구현체 — 인터페이스로 깔끔히 추상화.
12
+ - **`ManualLotteriesGenerator(manualCount, onReceiveNumbers: () -> List<Int>)`** — *View 의존성 차단*하면서 *수동 번호 입력 시점*을 람다로 주입.
13
+ - **`Count` 원시값 포장**으로 수동 검증 응집.
14
+ - **`LottoMachine`을 *상태 보유 객체*로** — `availableCount`, `currentLotteries` 등 진행 상태 명시화.
15
+ - **수동 로또 generator의 테스트 — `trial` 카운터로 *시나리오 검증***.
16
+ - **자가 의문 PR에 풍부히 명시** — *MatchCount 원시값 포장 기준*, *view 테스트 생략의 의미*, *Manager의 추상 깊이* 등.
17
+
18
+ ## 못한 점 (설계 관점)
19
+
20
+ ### 1. `Lottie` vs `lotteries` 용어 혼용
21
+
22
+ ```kotlin
23
+ private fun purchaseLottie(.) =.
24
+ fun showPurchasedLottie(lottos: List<Lotto>) =.
25
+ val lotteries = randomLottoGameManager.generateLotteries(.)
26
+ ```
27
+
28
+ 리뷰어: "어떨 때는 Lottie라는 용어를 쓰고 어떨 때는 lotteries라는 용어를 쓰는 것처럼 보이는군요. 이 둘을 *다른 의미로 쓰고 있나요? 아니면 같은 의미*로 쓰고 있나요?" 학생: "같은 의미의 변수들을 *다른 용어로 활용*하면 읽는 입장에서 혼란이 있을 것이라는 것을 알게 되었습니다. 통일성을 위하여 lotteries라는 용어로 변경하였습니다!" — 같은 개념은 *한 용어로 고정*.
29
+
30
+ ### 2. `RandomLottoGameManager` — *Random*이 어디서 나오는가
31
+
32
+ ```kotlin
33
+ class RandomLottoGameManager(private val lottoGenerator: LottoGenerator) : LottoGameManager {
34
+ override fun generateLotteries(purchaseExpense: Int) = lottoGenerator.generate(Money(purchaseExpense))
35
+ override fun generateWinningLotto(winningNumbers: List<Int>) = Lotto(*(winningNumbers.toIntArray()))
36
+ override fun generateBonusLottoNumber(bonusNumber: Int, winningLotto: Lotto) = LottoNumber(bonusNumber, winningLotto)
37
+ }
38
+ ```
39
+
40
+ 리뷰어: "솔직히 RandomLottoGameManager의 *어디가 Random*한 것인지, 코드를 처음 보는 사람 입장이라고 가정하면 *파악하기 어렵습니다*. 실제 랜덤을 담당하는 코드는 LotteryGenerator 중 AutoLottoGenerator 안의, NumbersGenerator 중 RandomNumbersGenerator까지로 이어지게 됩니다. 결국 *랜덤 요소를 가지고 있어 테스트하기 어려운 model*이 `RandomNumbersGenerator`, `AutoLottoGenerator`, `RandomLottoGameManager` *3개나 되어 버리게* 되었습니다. 이런 구조로는 프로젝트가 커질수록 (*Manager를 관리하는 Manager가 생기는 경우*가 많습니다), 점점 테스트 불가능한 model들이 많아지리라 생각됩니다." — *추상화 단계*가 *테스트 불가 영역*을 *3중*으로 늘림. 후속 라운드에서 학생: "랜덤적인 요소를 가진 클래스(RandomNumbersGenerator)를 controller에서 *직접 의존*하도록 함으로써 나머지 클래스들의 *테스트가 가능*하도록 변경." — *국소화*.
41
+
42
+ ### 3. `RandomLottoGameManager` 명명 — "*Wrapper 클래스를 가져오기 위한 용도*"
43
+
44
+ 학생 PR 설명: "입력값을 바탕으로 Wrapper 클래스를 가져오기 위한 용도의 객체 추가." 리뷰어: "model에 새로 추가된 것은 LottoGameManager 인터페이스와 RandomLottoGameManager가 유일한데 이것이 '*Wrapper 클래스를 가져오기 위한 용도의 객체*'인 건가요? 아마 `List<Lotto>`와 `LottoNumber`를 *원시값 '포장(wrapper)' 클래스*라고 표현하시는 것 같고, 입력받은 숫자들을 원시값으로 포장 객체들로 바꾸어 반환하시기 때문에 그렇게 하신 것 같습니다. 그냥 LottoGameManager라고 하면 *좀더 코드를 읽기 쉬웠을* 듯합니다. 혹시 다른 클래스가 있나, *다시 한 번 체크하며 읽어야* 했습니다." — *PR 설명 어휘*가 코드 이해를 어렵게 함.
45
+
46
+ ### 4. 랜덤 generator의 테스트 — `assertDoesNotThrow` 한정
47
+
48
+ ```kotlin
49
+ @Test
50
+ fun `유효한 금액이 입력되었다면, 금액에 맞는 개수의 로또가 생성된다`() {
51
+ val expectedSize = 6
52
+ val actualSize = randomLottoGameManager.generateLotteries(6100).size
53
+ assertThat(actualSize).isEqualTo(expectedSize)
54
+ }
55
+
56
+ @Test
57
+ fun `유효한 우승 로또의 번호와 우승 번호와 중복되지 않는 보너스 번호가 입력되었다면, 보너스 번호를 위한 로또 숫자 객체가 생성된다`() {
58
+ assertDoesNotThrow {
59
+ randomLottoGameManager.generateBonusLottoNumber(7, Lotto(1, 2, 3, 4, 5, 6))
60
+ }
61
+ }
62
+ ```
63
+
64
+ 리뷰어: "랜덤 요소 때문에 구체적인 아웃풋을 테스트하지 못하고, *assertDoesNotThrow*만을 테스트하고 있습니다. 사실 *모든 종류의 아웃풋을 검증하는 assertThat 테스트는 당연하게도 assertDoesNotThrow를 포함하는 테스트*입니다. 이 테스트 이름이 좀 더 *유의미해질 수 있도록 단순한 assertDoesNotThrow 말고* 더 좋은 테스트를 작성해 주시면 좋을 것 같습니다." — *결과 검증이 안 되는 테스트*는 *함수 이름*의 약속을 못 지킴.
65
+
66
+ ### 5. `ExceptionHandler` 인터페이스 도입의 의문
67
+
68
+ ```kotlin
69
+ interface ExceptionHandler {
70
+ fun <T> handleInputValue(action: () -> T): T
71
+ fun handleOutputValue(action: () -> Unit)
72
+ }
73
+ ```
74
+
75
+ 리뷰어: "ExceptionHandler를 *별도의 인터페이스로 선언*하신 이유가 궁금합니다. input을 콘솔 입력이 아니라, 안드로이드를 통한 입력, 블루투스를 통한 입력 등등을 가정하셨기에 추상화하신 건가요? 그렇다면 *입력받는 부분이 아닌 입력 값에 대한 검증이 왜 여러 개가 필요한 경우*가 있는지 궁금해서 여쭈어봅니다. 입력값 검증의 요구사항이 *바뀌었을 때를 대비*하기 위함이라면, 요구사항이 바뀌기 전의 *과거의 로직은 레거시 취급*받아 *없어지도록* 저는 구조를 짤 것 같아서요." — 추상화는 *현재의 다양성*이 있을 때 비로소 정당화.
76
+
77
+ ### 6. View 테스트 생략 — 학생 자가 의문
78
+
79
+ 학생: "view에 대한 테스트를 생략한다는 것이 *문제가 된다는 것으로 배우거나 들어본 바는 없었습니다*. 미션에서도 *UI 로직은 제외*하고 테스트를 진행하라는 요구 조건. 다만 *입력값이 null인지 여부를 검증*한다는 것이 저에게는 중요한 것으로 느껴졌던 것 같습니다." 후속: "수동 로또의 요구사항을 확인하면서 *논리적 오류에 대해서만 예외*를 던져야 한다는 Kotlin의 예외 처리 방식을 알게 되었습니다. 크루들과 이야기를 나누어 보았을 때, *사용자로부터 입력을 받는 부분은 논리적인 오류가 아니라는 결론*을 얻을 수 있었는데 이것으로 *입력값이 null일 때 예외를 던지는지 여부를 테스트로 확인할 필요가 없어*지게 되었다고 생각하였습니다."
80
+
81
+ ### 7. `LottoNumber(number: Int, winningLotto: Lotto)` 부생성자 — 보너스 검증
82
+
83
+ ```kotlin
84
+ constructor(number: Int, winningLotto: Lotto) : this(number) {
85
+ val winningLottoNumbers = winningLotto.numbers.map { it.number }
86
+ require(number !in winningLottoNumbers) { EXCEPTION_DUPLICATE_BONUS_NUMBER_FORMAT }
87
+ }
88
+ ```
89
+
90
+ 리뷰어: "로직의 일부를 domain으로 옮겼다는 게 이 부분을 말씀하시는 건가요? 하지만 *관련해서 추가된 테스트 코드는 보이지를 않*아서 여쭈어봅니다." 학생: "보너스 번호가 우승 번호와 중복될 때 예외를 던지는지에 관한 *테스트 케이스를 추가*하였습니다. 사실 미션 수행 과정에서 *TDD를 원활히 진행하지 못하여*, 도메인에서 들어가는 모든 로직에 대한 테스트 케이스를 작성하지 못하고 일부 로직에 대한 *테스트를 생략*하게 된 것 같습니다."
91
+
92
+ ### 8. `NumbersGenerator` → `LotteriesGenerator` 추상화 단계 상향
93
+
94
+ 리뷰어 제안: "기왕 NumbersGenerator라는 인터페이스를 선언해 주신 것처럼, *더 큰 단위로 Lotteries 그 자체를 만드는 인터페이스*를 선언해 보면 어떨까 제안해 봅니다. `fun interface LotteriesGenerator { fun generate(): List<Lotto> }`" — *추상의 단위*를 *Number*에서 *Lottery*로 한 단계 올림. 학생 후속 라운드에서 정확히 그렇게 구현:
95
+
96
+ ```kotlin
97
+ class ManualLotteriesGenerator(
98
+ private val manualCount: Count,
99
+ private val onReceiveNumbers: () -> List<Int>,
100
+ ) : LotteriesGenerator {
101
+ override fun generate(): List<Lotto> = List(manualCount.value) { Lotto(*onReceiveNumbers().toIntArray()) }
102
+ }
103
+ ```
104
+
105
+ 리뷰어 평가: "제 의도와 일치합니다. 수동 로또를 *무척 훌륭하게* 구현해 주셨습니다."
106
+
107
+ ### 9. `MatchCount` 원시값 포장 vs 단순 Int
108
+
109
+ 학생 README에서 *MatchCount 원시값 포장*을 TODO로 남김. 리뷰어: "Lotto 클래스의 `getMatchCount(other: Lotto): Int`에서 말하는 MatchCount를 말하는 것 같은데, *케이엠이 생각하는 원시값 포장을 해야 하는 값과 하지 말아야 하는 값을 구분하는 기준*이 있나요?" — *원시값 포장의 기준*을 학생 스스로 정리하도록.
110
+
111
+ ### 10. `LottoMachine`에 *발행된 lotteries 보관 + 추가* 패턴
112
+
113
+ 리뷰어: "lottoMachine에 *생성된 로또 번호를 넘겨주는 게 아니라*, 추상화된 LotteriesGenerator 자체를 넘겨서, *lottoMachine을 테스트*하는 것이었습니다. LotteriesGenerator가 인터페이스로 추상화되어 있기 때문에, *언제든 정해진 시나리오의 로또 번호를 생성하도록 강제*할 수 있고, 그렇게 하면 *LottoMachine의 상태가 어떻게 변하고 어떻게 동작하는지 그 결과를 예측*할 수 있게 됩니다." — `LottoMachine(generator: LotteriesGenerator)`이 더 깊은 추상.
114
+
115
+ ### 11. `LottoGameController` — 리뷰어 칭찬
116
+
117
+ 리뷰어: "저는 컨트롤러 코드가 비대하다고 생각하지 않습니다. 첫째로 컨트롤러의 *코드의 줄 수가 100줄 이하로 충분히 작고*, 둘째로 컨트롤러의 *그 어떤 메서드에서도 조건문과 반복문이 존재하지 않고*, 무슨 역할을 하는지 메서드가 충분히 작고 직관적입니다. 저는 *더 이상 분리하기 어려울 만큼* 정말 잘 분리를 해 주신 것 같습니다!"
118
+
119
+ ## 리뷰어 의견 요지
120
+
121
+ - **용어 일관성** — 같은 개념은 한 용어로.
122
+ - **랜덤은 *최외곽 1곳에 가두기*** — Random* Manager → Manager → Generator 3중은 *테스트 불가 영역 확장*.
123
+ - **클래스명에 *역할이 명시*** — `RandomLottoGameManager`는 *랜덤*이 어디서 들어오는지 코드에서 안 보임.
124
+ - **추상화 단위 상향** — `NumbersGenerator`(List<Int>)보다 `LotteriesGenerator`(List<Lotto>)가 *책임의 자연 단위*.
125
+ - **`assertDoesNotThrow`는 *함수명*에만**, 본문은 *결과 검증* 포함.
126
+ - **인터페이스 추상화의 정당화** = *현재의 다양성*. 미래 변경 대비 추상화는 *레거시 회피*가 더 자연.
127
+ - **수동 로또 generator의 *람다 주입*** — `onReceiveNumbers: () -> List<Int>`로 View 의존 차단.
128
+ - **LottoMachine에 *Generator 자체*를 주입** — 시나리오 강제 테스트.
129
+
130
+ - **대표 인용:**
131
+ > 랜덤 요소를 가지고 있어 테스트 하기 어려운 model이 `RandomNumbersGenerator`, `AutoLottoGenerator`, `RandomLottoGameManager` *3개나 되어버리게* 되었습니다. … 점점 *테스트 불가능한 model*들이 많아지리라 생각됩니다.
132
+ > — @ghojeong on `src/main/kotlin/model/RandomLottoGameManager.kt`
133
+
134
+ > 솔직히 RandomLottoGameManager의 *어디가 Random*한 것인지, 코드를 처음 보는 사람 입장이라고 가정하면 파악하기 어렵습니다.
135
+ > — @ghojeong on `src/main/kotlin/model/RandomLottoGameManager.kt`
136
+
137
+ > 모든 종류의 아웃풋을 검증하는 assertThat 테스트는 *당연하게도 assertDoesNotThrow를 포함하는 테스트*입니다.
138
+ > — @ghojeong on `src/test/kotlin/model/RandomLottoGameManagerTest.kt`
139
+
140
+ > 기왕 NumbersGenerator라는 인터페이스를 선언해 주신 것처럼, *더 큰 단위로 Lotteries 그 자체를 만드는 인터페이스*를 선언해 보면 어떨까 제안해 봅니다.
141
+ > — @ghojeong on `src/main/kotlin/lotto/model/NumbersGenerator.kt`
142
+
143
+ > LotteriesGenerator가 인터페이스로 추상화되어 있기 때문에, 언제든 *정해진 시나리오의 로또 번호를 생성*하도록 강제할 수 있고, 그렇게 하면 *LottoMachine의 상태가 어떻게 변하고 어떻게 동작하는지 그 결과를 예측*할 수 있게 됩니다.
144
+ > — @ghojeong on `src/main/kotlin/lotto/controller/LottoGameController.kt`
145
+
146
+ ## 얻은 교훈
147
+
148
+ - **용어 일관성 = 협업 비용 감소** — `Lottie`/`lotteries`처럼 같은 개념을 두 용어로 부르면 *읽는 사람이 매번 확인*.
149
+ - **랜덤은 *최외곽 1곳*에 가두기** — Random Manager → Manager → Generator 같은 *3중 추상*은 *테스트 불가 영역을 확장*. Controller가 *직접 RandomNumbersGenerator만* 의존하고 나머지 도메인은 *번호를 받아 처리*.
150
+ - **클래스명에 *역할의 핵심***이 노출되어야 함 — `RandomLottoGameManager`의 *Random*이 코드에서 안 보이면 *부정확한 이름*.
151
+ - **추상화 단위는 *책임의 자연 단위*** — `List<Int>`보다 `List<Lotto>`가 도메인 책임의 단위. 추상이 *작은 단위*에 머무르면 *호출자가 한 번 더 변환* 필요.
152
+ - **추상화의 정당화 = *현재의 다양성*** — 미래 변경 대비 추상화는 *과설계*. 요구 변경 시 *레거시 교체*가 더 자연.
153
+ - **`assertDoesNotThrow`는 *함수 이름의 약속*만 지킬 뿐**, 본문은 *결과 검증*까지 포함해야 *함수명이 의미*를 가짐.
154
+ - **수동 generator의 *람다 주입*** — `onReceiveNumbers: () -> List<Int>` 같이 *View 의존을 람다로 추출*하면 *도메인 단위 테스트* 가능 + 시나리오 제어.
155
+ - **LottoMachine에 *Generator 자체*를 주입** — *로또 번호를 직접 받기*보다 *생성 정책*을 받으면, *상태 전이 시나리오*를 외부에서 강제할 수 있어 *기계 전체*를 단위 테스트 가능.
156
+ - **MatchCount 원시값 포장의 *기준*** — *행위가 있어야* 정당화. Int 반환에 머무르면 *wrapping 비용*만.
157
+ - **TDD 보존** — *일부 로직 테스트 생략*은 *후속 라운드에서 추가*되어야 하며, *변경 의도*가 PR에 명시되어야 함.
@@ -0,0 +1,161 @@
1
+ # PR #19 — [끄롱] 1단계 로또
2
+
3
+ - **Reviewee:** [@krrong](https://github.com/krrong)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/19
5
+ - **단계:** 1단계
6
+ - **리뷰어:** @laco-dev
7
+ - **라인 코멘트:** 79
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`WinningLotto`가 `Lotto`와 `BonusNumber`를 보유** — 역할 표현 잘됨.
12
+ - **`RandomGenerator` 인터페이스** — 테스트 가능성.
13
+ - **`Rank` enum + `valueOf(match, bonus)`** 팩토리.
14
+ - **`InputViewInterface` 도입** — View 의존성 분리 시도.
15
+
16
+ ## 못한 점 (설계 관점)
17
+
18
+ ### 1. `LottoNumber` 도메인 누락 → `Set<Int>` 그대로 노출
19
+
20
+ ```kotlin
21
+ class Lotto(val numbers: Set<Int>) {. }
22
+ ```
23
+
24
+ 리뷰어 핵심 지적:
25
+
26
+ > 로또에서 사용하는 숫자는 결국 Int 타입이라고 볼 수 있겠습니다. 그렇다면 외부에서 가져온 이 숫자들이 로또 번호라는 것을 어떻게 알 수 있을까요
27
+ > ```kotlin
28
+ > val lotto = Lotto(.)
29
+ > val number = lotto.numbers.first()
30
+ > foo(number)
31
+ >
32
+ > fun foo(number: Int) {
33
+ > // number가 로또 번호인가? 그럼 또 검증해야되나?
34
+ > }
35
+ > ```
36
+
37
+ → `LottoNumber` 값 객체로 추출하면 타입 시스템이 검증을 보장.
38
+
39
+ ### 2. `RandomGenerator` 이름의 모호함
40
+
41
+ ```kotlin
42
+ interface RandomGenerator {
43
+ fun generate(): Set<Int>
44
+ }
45
+ ```
46
+
47
+ > 단순히 RandomGenerator라는 이름이 1부터 45 사이의 중복되지 않은 숫자 6개를 반환한다는 것을 알 수 있을까요?
48
+
49
+ → `LottoNumberGenerator`처럼 *무엇을* 생성하는지 명시. 인터페이스 계약을 시그니처/이름으로 드러내기.
50
+
51
+ ### 3. `LottoStatistics`의 `compareNumbers`/`compareBonusNumber`가 public — 테스트만 위해 노출
52
+
53
+ ```kotlin
54
+ class LottoStatistics(val winningLotto: WinningLotto) {
55
+ fun compareNumbers(lotto: Lotto): Int {. } // ⚠ 테스트만 호출
56
+ fun compareBonusNumber(lotto: Lotto): Boolean {. } // ⚠ 테스트만 호출
57
+ fun compare(lotto: Lotto): Rank =.
58
+ }
59
+ ```
60
+
61
+ > 이 함수들은 테스트 코드에서만 사용되고 있어요. 테스트 코드를 위해 구현 코드가 public으로 노출되어서는 안됩니다.
62
+
63
+ ### 4. 함수 이름 모호 — `compare()`, `yield()`
64
+
65
+ ```kotlin
66
+ fun compare(lotto: Lotto): Rank =.
67
+ fun yield(): Double =.
68
+ ```
69
+
70
+ > compare(), yield()라는 함수 이름으로 하여금, 어떤 결과를 반환하는지 알 수 있을까요?
71
+
72
+ `compare`는 일반적으로 `-1/0/1` 반환을 시사. 도메인 어휘로 `match(lotto): Rank`, `profitRate(): Double`이 더 명확.
73
+
74
+ ### 5. **Tell-Don't-Ask 위반 — Statistics가 외부 객체의 정보로 직접 비교**
75
+
76
+ ```kotlin
77
+ class LottoStatistics(val winningLotto: WinningLotto) {
78
+ fun compareNumbers(lotto: Lotto): Int {
79
+ val winningNumbers = winningLotto.getWinningNumbers() // ⚠ winningLotto의 정보를 꺼냄
80
+ return lotto.numbers.filter { number -> // ⚠ lotto의 정보도 꺼냄
81
+ winningNumbers.contains(number)
82
+ }.size
83
+ }
84
+ }
85
+ ```
86
+
87
+ 리뷰어 가이드 (Tell-Don't-Ask의 모범):
88
+
89
+ > 몇개가 일치하는지 요청해서 결과를 받아오도록 해보세요. 객체지향 프로그래밍에서는 이 개념을 메시지를 보낸다 라고 표현합니다.
90
+ > ```kotlin
91
+ > val matchedRank: Rank = winningLotto.match(lotto)
92
+ > ```
93
+
94
+ → Statistics가 직접 계산하지 말고 WinningLotto에게 메시지 전달.
95
+
96
+ ### 6. Rank 집계 자료구조 부재
97
+
98
+ ```kotlin
99
+ fun compare(lotto: Lotto): Rank = Rank.valueOf(.)
100
+ // ⚠ 각 Rank에 몇 개 일치하는지를 어떻게 셀까?
101
+ ```
102
+
103
+ > Rank에 해당하는 값에 총 몇개의 당첨 갯수가 있는지를 확인하는 방법으로 적절한 자료구조는 무엇일까요?
104
+
105
+ → `Map<Rank, Int>` 또는 더 깔끔하게 `groupingBy { it }.eachCount()`.
106
+
107
+ ### 7. `WinningLotto`가 1~45 범위 검증 직접 수행 (중복)
108
+
109
+ ```kotlin
110
+ class WinningLotto(val lotto: Lotto, val bonusNumber: Int) {
111
+ init {
112
+ require(!lotto.numbers.contains(bonusNumber)) { ERROR_CONTAIN_BONUS_NUMBER_IN_LOTTO }
113
+ require(bonusNumber in MINIMUM_LOTTO_RANGE..MAXIMUM_LOTTO_RANGE) { ERROR_BONUS_NUMBER_RANGE }
114
+ }
115
+ }
116
+ ```
117
+
118
+ `Lotto` 내부에서도 `numbers in 1..45` 검증. `LottoNumber` 값 객체가 있으면 양쪽에서 사라짐.
119
+
120
+ ### 8. `let` 오용
121
+
122
+ ```kotlin
123
+ fun valueOf(countOfMatch: Int, matchBonus: Boolean): Rank {
124
+ return values().find { it.countOfMatch == countOfMatch }.let { matchResult ->
125
+ if (matchResult == SECOND && !matchBonus) return@let.
126
+ }
127
+ }
128
+ ```
129
+
130
+ > let에 대한 올바른 사용방법이 아닙니다. when 문을 이용해서 표현 해 보도록 하세요.
131
+
132
+ ## 리뷰어 의견 요지
133
+
134
+ 리뷰어 @laco-dev의 메시지:
135
+
136
+ 1. **`LottoNumber` 도메인 추출**이 모든 안티패턴의 출발점 — 범위 검증 중복, 일반 Int 노출, "이 Int가 로또 번호인가?" 의문 모두 해결.
137
+
138
+ 2. **Tell-Don't-Ask = 메시지 전달**. Statistics가 두 객체의 정보를 꺼내서 비교 = feature-envy. `winningLotto.match(lotto): Rank` 한 메시지.
139
+
140
+ 3. **함수명 = 도메인 어휘**. `compare`처럼 일반 어휘 회피, `match`, `profitRate` 등.
141
+
142
+ 4. **테스트만을 위한 public 노출 금지** — racingcar에서도 반복 등장.
143
+
144
+ 5. **인터페이스 이름이 *계약*을 드러내야** — `RandomGenerator`만으로는 "무엇을 생성하는지" 모름.
145
+
146
+ - **대표 인용:**
147
+ > 몇개가 일치하는지 요청해서 결과를 받아오도록 해보세요. 객체지향 프로그래밍에서는 이 개념을 메시지를 보낸다 라고 표현합니다. `val matchedRank: Rank = winningLotto.match(lotto)`
148
+ >
149
+ > — @laco-dev on `src/main/kotlin/domain/LottoStatistics.kt`
150
+
151
+ > 로또 번호라는 역할을 만들어서 가지도록 해 보면 어떨까요? 마찬가지로 로또 번호를 최대 6개 까지만 가져야 한다면, 그러한 역할을 가지는 객체를 만들어 볼 수 있겠습니다.
152
+ >
153
+ > — @laco-dev on `src/main/kotlin/domain/Lotto.kt`
154
+
155
+ ## 얻은 교훈
156
+
157
+ - **`LottoNumber`는 lotto 미션의 *마스터 키***. 1-45 범위, 중복 검증, 보너스 비교 모두 이 한 값 객체로 해결.
158
+ - **Tell-Don't-Ask의 lotto 적용** = `winningLotto.match(lotto): Rank`. Statistics 같은 외부 객체가 비교 로직을 갖지 말고, 도메인 소유자(WinningLotto)에게 메시지.
159
+ - **함수명 컨벤션 차이**: `compare()` = 비교(-1/0/1), `match()` = 일치 확인. 도메인 어휘를 신중히.
160
+ - **인터페이스 이름 = 계약 요약**. `RandomGenerator`보다 `LottoNumberGenerator`가 의도 명확.
161
+ - **`Map<Rank, Int>` 자료구조** = lotto 통계의 표준. 등수별 개수를 한 자료구조로.
@@ -0,0 +1,73 @@
1
+ # PR #41 — [크롱] 2단계 로또
2
+
3
+ - **Reviewee:** [@krrong](https://github.com/krrong)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/41
5
+ - **단계:** 2단계
6
+ - **리뷰어:** @laco-dev
7
+ - **라인 코멘트:** 45
8
+
9
+ ## 못한 점 + 핵심 지적
10
+
11
+ ### 1. 함수명 `makeMoney()` vs `Money(.)`
12
+
13
+ ```kotlin
14
+ fun makeMoney(input: String): Money =.
15
+ ```
16
+
17
+ > 마이너한 내용인데, Money는 왜 makeMoney()가 아닐까요?
18
+
19
+ → 팩토리는 보통 `Money.of(input)` 또는 `Money(value)` 직접. `makeXxx` 패턴은 일관성 떨어짐.
20
+
21
+ ### 2. 0 이상 검증을 Controller에서
22
+
23
+ ```kotlin
24
+ class LottoController {
25
+ fun run() {
26
+ val count = readManualCount()
27
+ require(count >= 0) {. } // ⚠ Controller에서 비즈니스 로직
28
+ }
29
+ }
30
+ ```
31
+
32
+ > 항상 0 이상의 숫자를 받아야 한다는 것도 객체를 만들어서 처리해보세요. (비즈니스 로직을 도메인 모델로 옮긴다는 의미입니다)
33
+
34
+ ### 3. `runCatching` 중복 — Controller + UI
35
+
36
+ ```kotlin
37
+ // Controller
38
+ runCatching {. }.getOrElse {. }
39
+ // UI
40
+ runCatching {. }.getOrElse {. }
41
+ ```
42
+
43
+ > `runCatching {. }` 로직이 컨트롤러, UI 두군데에 중복해서 있습니다. 올바르지 않은 값으로 Money를 만들었을때 누구의 잘못이 된다고 볼 수 있을까요?
44
+
45
+ ### 4. 수익률 계산이 Controller에
46
+
47
+ ```kotlin
48
+ val profitRate = totalPrize.toDouble() / money.value // ⚠ Controller가 계산
49
+ ```
50
+
51
+ > 수익률을 계산하는 로직도 도메인 로직으로 분리해보세요.
52
+
53
+ ### 5. 로또 가격 1000원을 Controller가 앎
54
+
55
+ ```kotlin
56
+ val count = money.value / 1000 // ⚠ Controller 안에 1000원
57
+ ```
58
+
59
+ > 로또 한장의 가격을 컨트롤러가 알아야 할 필요가 있을까요?
60
+
61
+ ### 6. Lotto.toList 반환 타입
62
+
63
+ ```kotlin
64
+ fun toList(): List<Int> =. // ⚠ List<LottoNumber>여야 하지 않나?
65
+ ```
66
+
67
+ > toList()는 `List<LottoNumber>`를 반환해야 하지 않을까요?
68
+
69
+ ## 얻은 교훈
70
+
71
+ - **도메인 객체로 검증/계산 이동** — Controller에 0 이상, 1000원, 수익률 같은 *비즈니스 로직*이 모이면 god-controller.
72
+ - **`runCatching` 중복 = 책임 위치 결정 필요**. Money 생성 실패는 *Money의 책임*. Controller/UI는 결과만.
73
+ - **`toList()` 타입 — 도메인 타입 유지**.