tmscli 0.4.1__tar.gz → 0.6.0__tar.gz
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.
- {tmscli-0.4.1 → tmscli-0.6.0}/PKG-INFO +1 -1
- {tmscli-0.4.1 → tmscli-0.6.0}/pyproject.toml +2 -1
- tmscli-0.6.0/src/tmscli/.scores/high_scores.csv +1 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/index.html +1 -1
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/main.py +77 -12
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/play.html +2 -2
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/screenshots.html +0 -7
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/style.css +6 -88
- tmscli-0.6.0/update.sh +34 -0
- tmscli-0.4.1/update.sh +0 -34
- {tmscli-0.4.1 → tmscli-0.6.0}/README.md +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/initialise.sh +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/.gitkeep +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/__init__.py +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/about.html +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/changelog.html +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/img/big.jpg +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/img/midgame.jpg +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/img/new_board.jpg +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/img/win.jpg +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/src/tmscli/install.html +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/video and storyboard/pyauto.py +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/video and storyboard/script.txt +0 -0
- {tmscli-0.4.1 → tmscli-0.6.0}/video and storyboard/vid.py +0 -0
|
@@ -4,10 +4,11 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tmscli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
description = "runs minesweeper in your terminal, type rules for how to play"
|
|
9
9
|
readme="README.md"
|
|
10
10
|
dependencies = []
|
|
11
11
|
|
|
12
12
|
[project.scripts]
|
|
13
13
|
tms = "tmscli.main:run"
|
|
14
|
+
top_score = "tmscli.main:get_top"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
username,time,size,mine num, score
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<div class="header-inner">
|
|
13
13
|
<div class="logo">tmscli</div>
|
|
14
14
|
<nav>
|
|
15
|
-
<a href="index.html">main</a>
|
|
15
|
+
<a href="index.html" class="active">main</a>
|
|
16
16
|
<a href="about.html">about</a>
|
|
17
17
|
<a href="install.html">installation + usage</a>
|
|
18
18
|
<a href="screenshots.html">screenshots</a>
|
|
@@ -1,11 +1,43 @@
|
|
|
1
1
|
import random
|
|
2
2
|
import argparse
|
|
3
3
|
import importlib.metadata
|
|
4
|
+
import csv
|
|
5
|
+
from time import time
|
|
6
|
+
colors=['\033[31m','\033[32m','\033[33m','\033[34m','\033[35m','\033[36m','\033[37m','\033[38m','\033[39m']
|
|
7
|
+
MINE='\033[30m'
|
|
8
|
+
FLAG='\033[29m'
|
|
9
|
+
RESET = '\033[0m'
|
|
10
|
+
|
|
4
11
|
class minesweeper():
|
|
5
12
|
def __init__(self,size,num):
|
|
6
13
|
self.size=size
|
|
7
14
|
self.num=num
|
|
8
15
|
['uncovered?','flagged?','display']
|
|
16
|
+
def log(self,user,t,size,num,score):
|
|
17
|
+
with open('./src/tmscli/.scores/high_scores.csv', mode='a', newline='', encoding='utf-8') as file:
|
|
18
|
+
writer = csv.writer(file)
|
|
19
|
+
writer.writerow([user,t,size,num,round(score)])
|
|
20
|
+
|
|
21
|
+
def get_score(self,t,size,num):
|
|
22
|
+
ratio=size/num
|
|
23
|
+
score=1000/(t*ratio)
|
|
24
|
+
return t,size,num,score
|
|
25
|
+
def colored(self,string):
|
|
26
|
+
new=f'|'
|
|
27
|
+
c=0
|
|
28
|
+
for i in string:
|
|
29
|
+
c+=1
|
|
30
|
+
if i != '|':
|
|
31
|
+
if i in ['0','1','2','3','4','5','6','7','8']:
|
|
32
|
+
new+=f'{colors[int(i)]}{i}{RESET}'
|
|
33
|
+
elif i == 'M':
|
|
34
|
+
new+=f'{MINE}{i}{RESET}'
|
|
35
|
+
elif i == 'F':
|
|
36
|
+
new+=f'{FLAG}{i}{RESET}'
|
|
37
|
+
else:
|
|
38
|
+
new+=' '
|
|
39
|
+
new+='|'
|
|
40
|
+
return new
|
|
9
41
|
def print_board(self,board):
|
|
10
42
|
top=' '+(self.size*2)*'_'
|
|
11
43
|
print(top)
|
|
@@ -18,7 +50,7 @@ class minesweeper():
|
|
|
18
50
|
buffer+='F'+' '
|
|
19
51
|
else:
|
|
20
52
|
buffer+=' '+' '
|
|
21
|
-
print(buffer[:-1]+'|')
|
|
53
|
+
print(self.colored(buffer[:-1]+'|'))
|
|
22
54
|
bottom=' '+(len(top)-1)*'-'
|
|
23
55
|
print(bottom)
|
|
24
56
|
def get_mines(self):
|
|
@@ -58,18 +90,23 @@ class minesweeper():
|
|
|
58
90
|
board[i][j][2]=c
|
|
59
91
|
return board
|
|
60
92
|
def print_ending(self,board):
|
|
93
|
+
top=' '+(self.size*2)*'_'
|
|
94
|
+
print(top)
|
|
61
95
|
for i in board:
|
|
62
96
|
buffer=''
|
|
63
97
|
for j in i:
|
|
64
98
|
buffer+=str(j[2])+' '
|
|
65
|
-
print(buffer)
|
|
66
|
-
|
|
99
|
+
print(self.colored(buffer))
|
|
100
|
+
bottom=' '+(len(top)-1)*'-'
|
|
101
|
+
print(bottom)
|
|
67
102
|
def check_success(self,board):
|
|
68
103
|
for i in board:
|
|
69
104
|
for j in i:
|
|
70
105
|
if j[2]!='M':
|
|
71
106
|
if not j[0]:
|
|
72
107
|
return False
|
|
108
|
+
# end=time()
|
|
109
|
+
|
|
73
110
|
return True
|
|
74
111
|
def check_death(self,board):
|
|
75
112
|
for i in board:
|
|
@@ -84,7 +121,7 @@ class minesweeper():
|
|
|
84
121
|
return True
|
|
85
122
|
elif self.check_success(board):
|
|
86
123
|
print('YOU WIN')
|
|
87
|
-
return
|
|
124
|
+
return 1
|
|
88
125
|
return False
|
|
89
126
|
def richochet(self,board,coord):
|
|
90
127
|
x,y=coord
|
|
@@ -108,6 +145,7 @@ terminal_minesweeper=minesweeper(9,5)
|
|
|
108
145
|
def throw():
|
|
109
146
|
print('unrecognised command, please try again')
|
|
110
147
|
def main_loop(board):
|
|
148
|
+
start=time()
|
|
111
149
|
try:
|
|
112
150
|
while True:
|
|
113
151
|
terminal_minesweeper.print_board(board)
|
|
@@ -142,17 +180,18 @@ def main_loop(board):
|
|
|
142
180
|
else:
|
|
143
181
|
throw()
|
|
144
182
|
continue
|
|
145
|
-
|
|
183
|
+
k=terminal_minesweeper.check(board)
|
|
184
|
+
if k:
|
|
146
185
|
terminal_minesweeper.print_ending(board)
|
|
186
|
+
if k==1:
|
|
187
|
+
end=time()
|
|
188
|
+
print(f'Score:{round(terminal_minesweeper.get_score(round(end-start,3),terminal_minesweeper.size,terminal_minesweeper.num)[3])}')
|
|
189
|
+
a,b,c,d=terminal_minesweeper.get_score(round(end-start,3),terminal_minesweeper.size,terminal_minesweeper.num)
|
|
190
|
+
terminal_minesweeper.log(input('Username >>> '),a,b,c,d)
|
|
147
191
|
exit()
|
|
148
192
|
except KeyboardInterrupt:
|
|
149
193
|
print('Interrupted')
|
|
150
194
|
terminal_minesweeper.print_ending(board)
|
|
151
|
-
except:
|
|
152
|
-
if terminal_minesweeper.check(board):
|
|
153
|
-
exit()
|
|
154
|
-
print('ERROR')
|
|
155
|
-
terminal_minesweeper.print_ending(board)
|
|
156
195
|
def run():
|
|
157
196
|
try:
|
|
158
197
|
__version__ = importlib.metadata.version("tmscli")
|
|
@@ -192,7 +231,6 @@ def run():
|
|
|
192
231
|
mines=terminal_minesweeper.get_mines()
|
|
193
232
|
board=terminal_minesweeper.create_starting_board(mines)
|
|
194
233
|
main_loop(board)
|
|
195
|
-
|
|
196
234
|
def print_rules():
|
|
197
235
|
place='''
|
|
198
236
|
y------>
|
|
@@ -226,4 +264,31 @@ If you step on a mine you lose, the number on the square is how many mines are a
|
|
|
226
264
|
print(i.rstrip())
|
|
227
265
|
input()
|
|
228
266
|
input('press enter to start:')
|
|
229
|
-
|
|
267
|
+
def upper(l):
|
|
268
|
+
return int(l[4])
|
|
269
|
+
def get_top(num=5):
|
|
270
|
+
p=argparse.ArgumentParser(description='scoreboard')
|
|
271
|
+
p.add_argument(
|
|
272
|
+
'-s','--scores',
|
|
273
|
+
type=int,
|
|
274
|
+
default=5,
|
|
275
|
+
help='set size to x'
|
|
276
|
+
)
|
|
277
|
+
args=p.parse_args()
|
|
278
|
+
if args.scores:
|
|
279
|
+
num=args.scores
|
|
280
|
+
with open('./src/tmscli/.scores/high_scores.csv', mode='r') as file:
|
|
281
|
+
reader=csv.reader(file)
|
|
282
|
+
header=next(reader)
|
|
283
|
+
head=['time','size','mines','score']
|
|
284
|
+
r=list(reader)
|
|
285
|
+
r.sort(key=upper)
|
|
286
|
+
r.reverse()
|
|
287
|
+
for i in range(num):
|
|
288
|
+
print(str(i+1)+'. '+r[i][0])
|
|
289
|
+
for j in range(4):
|
|
290
|
+
print(' '+head[j]+': '+ r[i][j+1])
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# get_top()
|
|
294
|
+
# run()
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
<div class="embed-card">
|
|
30
30
|
<iframe
|
|
31
|
-
src="https://
|
|
31
|
+
src="https://onecompiler.com/python/456p63wg4"
|
|
32
32
|
title="tmscli on Programiz"
|
|
33
33
|
loading="lazy"
|
|
34
34
|
allow="clipboard-write"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
|
|
40
40
|
<p class="embed-fallback">
|
|
41
41
|
If the embed doesn't load, open it directly:
|
|
42
|
-
<a href="https://
|
|
42
|
+
<a href="https://onecompiler.com/python/456p63wg4" target="_blank" rel="noopener">
|
|
43
43
|
programiz.com/online-compiler/0cfPcHKGhg10y
|
|
44
44
|
</a>
|
|
45
45
|
</p>
|
|
@@ -25,13 +25,6 @@
|
|
|
25
25
|
<main class="container">
|
|
26
26
|
<h1>screenshots</h1>
|
|
27
27
|
<p class="subhead">See tmscli in action — straight from the terminal.</p>
|
|
28
|
-
|
|
29
|
-
<!--
|
|
30
|
-
Add your screenshots below.
|
|
31
|
-
Each .screenshot-card is one entry. Duplicate the block as needed.
|
|
32
|
-
Replace the <img> src with your actual image path, e.g. "img/fresh-board.png"
|
|
33
|
-
-->
|
|
34
|
-
|
|
35
28
|
<div class="screenshot-grid">
|
|
36
29
|
|
|
37
30
|
<div class="screenshot-card">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
|
|
3
3
|
* {
|
|
4
4
|
margin: 0;
|
|
@@ -16,7 +16,7 @@ body {
|
|
|
16
16
|
min-height: 100vh;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
header {
|
|
21
21
|
background: #0f2b3d;
|
|
22
22
|
color: #e2e8f0;
|
|
@@ -73,8 +73,8 @@ nav a.active {
|
|
|
73
73
|
font-weight: 600;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
.
|
|
76
|
+
|
|
77
|
+
.containe {
|
|
78
78
|
max-width: 1100px;
|
|
79
79
|
margin: 2rem auto 3rem;
|
|
80
80
|
padding: 0 2rem;
|
|
@@ -118,7 +118,7 @@ p {
|
|
|
118
118
|
color: #1e2f3f;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
.card-grid {
|
|
123
123
|
display: grid;
|
|
124
124
|
grid-template-columns: 1fr 1fr;
|
|
@@ -147,7 +147,7 @@ p {
|
|
|
147
147
|
padding-bottom: 0.5rem;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
.lorem-block {
|
|
152
152
|
background: #eef6fb;
|
|
153
153
|
padding: 2rem 2rem 1.2rem;
|
|
@@ -159,8 +159,6 @@ p {
|
|
|
159
159
|
.lorem-block h2 {
|
|
160
160
|
margin-top: 0;
|
|
161
161
|
}
|
|
162
|
-
|
|
163
|
-
/* about page */
|
|
164
162
|
.about-section {
|
|
165
163
|
background: #ffffff;
|
|
166
164
|
padding: 1.8rem 2rem 1rem;
|
|
@@ -174,7 +172,6 @@ p {
|
|
|
174
172
|
margin-top: 0;
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
/* installation + usage */
|
|
178
175
|
.install-card {
|
|
179
176
|
background: #0f2b3d;
|
|
180
177
|
color: #e2e8f0;
|
|
@@ -253,7 +250,6 @@ pre code {
|
|
|
253
250
|
.dependency-link:hover{
|
|
254
251
|
color:rgb(125,125,150);
|
|
255
252
|
}
|
|
256
|
-
/* footer */
|
|
257
253
|
footer {
|
|
258
254
|
text-align: center;
|
|
259
255
|
padding: 1.8rem 2rem;
|
|
@@ -264,51 +260,6 @@ footer {
|
|
|
264
260
|
margin-top: 1rem;
|
|
265
261
|
}
|
|
266
262
|
|
|
267
|
-
/* responsive */
|
|
268
|
-
@media (max-width: 700px) {
|
|
269
|
-
.header-inner {
|
|
270
|
-
flex-direction: column;
|
|
271
|
-
gap: 0.8rem;
|
|
272
|
-
align-items: flex-start;
|
|
273
|
-
padding: 1rem 1.5rem;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
nav {
|
|
277
|
-
gap: 1.2rem;
|
|
278
|
-
width: 100%;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.container {
|
|
282
|
-
padding: 0 1.5rem;
|
|
283
|
-
margin-top: 1.5rem;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
h1 {
|
|
287
|
-
font-size: 2rem;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
.subhead {
|
|
291
|
-
font-size: 1rem;
|
|
292
|
-
padding-left: 0.8rem;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.card-grid {
|
|
296
|
-
grid-template-columns: 1fr;
|
|
297
|
-
gap: 1.2rem;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
.install-card,
|
|
301
|
-
.about-section,
|
|
302
|
-
.usage-section,
|
|
303
|
-
.lorem-block {
|
|
304
|
-
padding: 1.5rem 1.2rem 0.8rem;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
pre {
|
|
308
|
-
padding: 0.8rem 1rem;
|
|
309
|
-
font-size: 0.85rem;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
263
|
.changelog-entry {
|
|
313
264
|
background: #ffffff;
|
|
314
265
|
padding: 1.8rem 2rem 1.2rem;
|
|
@@ -355,24 +306,7 @@ footer {
|
|
|
355
306
|
margin-top: 0.8rem;
|
|
356
307
|
}
|
|
357
308
|
|
|
358
|
-
/* responsive for new pages */
|
|
359
|
-
@media (max-width: 700px) {
|
|
360
|
-
.screenshot-grid {
|
|
361
|
-
grid-template-columns: 1fr;
|
|
362
|
-
gap: 1.2rem;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
.screenshot-card,
|
|
366
|
-
.changelog-entry {
|
|
367
|
-
padding: 1.5rem 1.2rem 0.8rem;
|
|
368
|
-
}
|
|
369
309
|
|
|
370
|
-
.screenshot-card pre {
|
|
371
|
-
font-size: 0.7rem;
|
|
372
|
-
padding: 0.8rem;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/* ---- tables & lists (usage page) ---- */
|
|
376
310
|
|
|
377
311
|
.flags-table {
|
|
378
312
|
width: 100%;
|
|
@@ -429,16 +363,6 @@ footer {
|
|
|
429
363
|
border-bottom: none;
|
|
430
364
|
}
|
|
431
365
|
|
|
432
|
-
@media (max-width: 700px) {
|
|
433
|
-
.flags-table {
|
|
434
|
-
font-size: 0.85rem;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.flags-table th,
|
|
438
|
-
.flags-table td {
|
|
439
|
-
padding: 0.6rem 0.7rem;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
366
|
.embed-card {
|
|
443
367
|
background: #ffffff;
|
|
444
368
|
border: 1px solid #e1eef5;
|
|
@@ -467,9 +391,3 @@ footer {
|
|
|
467
391
|
font-weight: 500;
|
|
468
392
|
word-break: break-all;
|
|
469
393
|
}
|
|
470
|
-
|
|
471
|
-
@media (max-width: 700px) {
|
|
472
|
-
.embed-frame {
|
|
473
|
-
height: 550px;
|
|
474
|
-
}
|
|
475
|
-
}
|
tmscli-0.6.0/update.sh
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Exit immediately if any command fails
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
read commit
|
|
7
|
+
read pypi
|
|
8
|
+
if [ "$pypi" == "yes" ]; then
|
|
9
|
+
|
|
10
|
+
echo "* Building the package with Hatch..."
|
|
11
|
+
hatch build
|
|
12
|
+
|
|
13
|
+
echo "* Publishing the package to PyPI..."
|
|
14
|
+
hatch publish
|
|
15
|
+
|
|
16
|
+
fi
|
|
17
|
+
if [ "$commit" == "yes" ]; then
|
|
18
|
+
echo "* Pulling latest changes from remote Git repository..."
|
|
19
|
+
git pull || echo " Pull skipped or failed, continuing..."
|
|
20
|
+
|
|
21
|
+
echo "* Staging changes..."
|
|
22
|
+
git add .
|
|
23
|
+
|
|
24
|
+
echo "* Committing changes..."
|
|
25
|
+
read reason
|
|
26
|
+
git commit -m "$reason"
|
|
27
|
+
|
|
28
|
+
echo "* Pushing changes to remote..."
|
|
29
|
+
git push
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "* Updating current installed module"
|
|
33
|
+
pip install --upgrade tmscli
|
|
34
|
+
echo "* All steps completed successfully!"
|
tmscli-0.4.1/update.sh
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Exit immediately if any command fails
|
|
4
|
-
set -e
|
|
5
|
-
|
|
6
|
-
read commit
|
|
7
|
-
read pypi
|
|
8
|
-
if [ "$pypi" == "yes" ]; then
|
|
9
|
-
|
|
10
|
-
echo "Building the package with Hatch..."
|
|
11
|
-
hatch build
|
|
12
|
-
|
|
13
|
-
echo "Publishing the package to PyPI..."
|
|
14
|
-
hatch publish
|
|
15
|
-
|
|
16
|
-
fi
|
|
17
|
-
if [ "$commit" == "yes" ]; then
|
|
18
|
-
echo "Pulling latest changes from remote Git repository..."
|
|
19
|
-
git pull || echo "Pull skipped or failed, continuing..."
|
|
20
|
-
|
|
21
|
-
echo "Staging changes..."
|
|
22
|
-
git add .
|
|
23
|
-
|
|
24
|
-
echo "Committing changes..."
|
|
25
|
-
read reason
|
|
26
|
-
git commit -m "$reason"
|
|
27
|
-
|
|
28
|
-
echo "Pushing changes to remote..."
|
|
29
|
-
git push
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
echo "Updating current installed module"
|
|
33
|
-
pip install --upgrade tmscli
|
|
34
|
-
echo "All steps completed successfully!"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|