Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-deckform-filler
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
ygopro-deckform-filler
Commits
8f62bc29
Commit
8f62bc29
authored
Oct 23, 2025
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support direct load from ygocdb data
parent
4c8cf63d
Pipeline
#41215
passed with stages
in 4 minutes and 2 seconds
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
90 additions
and
12 deletions
+90
-12
.dockerignore
.dockerignore
+1
-0
.gitignore
.gitignore
+2
-1
src/app.controller.ts
src/app.controller.ts
+23
-2
src/app.service.ts
src/app.service.ts
+15
-1
src/card-data/card-data.service.ts
src/card-data/card-data.service.ts
+49
-8
No files found.
.dockerignore
View file @
8f62bc29
...
@@ -36,6 +36,7 @@ lerna-debug.log*
...
@@ -36,6 +36,7 @@ lerna-debug.log*
/data
/data
/output
/output
/config.yaml
/config.yaml
/ygocdb-data
.git*
.git*
Dockerfile
Dockerfile
...
...
.gitignore
View file @
8f62bc29
...
@@ -35,4 +35,5 @@ lerna-debug.log*
...
@@ -35,4 +35,5 @@ lerna-debug.log*
/data
/data
/output
/output
/config.yaml
/config.yaml
\ No newline at end of file
/ygocdb-data
\ No newline at end of file
src/app.controller.ts
View file @
8f62bc29
...
@@ -15,12 +15,22 @@ import {
...
@@ -15,12 +15,22 @@ import {
import
{
FileInterceptor
}
from
'
@nestjs/platform-express
'
;
import
{
FileInterceptor
}
from
'
@nestjs/platform-express
'
;
import
{
FileUploadDto
}
from
'
./dto/file-upload.dto
'
;
import
{
FileUploadDto
}
from
'
./dto/file-upload.dto
'
;
import
YGOProDeck
from
'
ygopro-deck-encode
'
;
import
YGOProDeck
from
'
ygopro-deck-encode
'
;
import
{
ApiError
,
BlankReturnMessageDto
,
DataQuery
}
from
'
nesties
'
;
import
{
ApiBlankResponse
,
ApiError
,
BlankReturnMessageDto
,
DataQuery
,
RequireToken
,
}
from
'
nesties
'
;
import
{
FillOptionsDto
}
from
'
./dto/fill-options.dto
'
;
import
{
FillOptionsDto
}
from
'
./dto/fill-options.dto
'
;
import
{
CardDataService
}
from
'
./card-data/card-data.service
'
;
@
Controller
()
@
Controller
()
export
class
AppController
{
export
class
AppController
{
constructor
(
private
readonly
appService
:
AppService
)
{}
constructor
(
private
readonly
appService
:
AppService
,
private
readonly
cardDataService
:
CardDataService
,
)
{}
@
Post
(
'
fill
'
)
@
Post
(
'
fill
'
)
@
ApiOperation
({
@
ApiOperation
({
...
@@ -53,4 +63,15 @@ export class AppController {
...
@@ -53,4 +63,15 @@ export class AppController {
}
}
return
this
.
appService
.
fillDeckForm
(
ydk
,
dto
);
return
this
.
appService
.
fillDeckForm
(
ydk
,
dto
);
}
}
@
Post
(
'
reload-ygocdb
'
)
@
ApiOperation
({
summary
:
'
Reload YGOCDB Data
'
,
})
@
ApiBlankResponse
()
@
RequireToken
()
async
reloadYGOCDBData
()
{
await
this
.
cardDataService
.
loadYGOCDBData
();
return
new
BlankReturnMessageDto
(
200
,
'
success
'
);
}
}
}
src/app.service.ts
View file @
8f62bc29
...
@@ -29,6 +29,7 @@ export class AppService extends ConsoleLogger {
...
@@ -29,6 +29,7 @@ export class AppService extends ConsoleLogger {
const
doc
=
await
PDFDocument
.
load
(
const
doc
=
await
PDFDocument
.
load
(
await
fs
.
promises
.
readFile
(
'
./resources/deck_cn.pdf
'
),
await
fs
.
promises
.
readFile
(
'
./resources/deck_cn.pdf
'
),
);
);
this
.
log
(
`Loaded PDF template for deck export.`
);
const
directDrawFields
=
[
'
name
'
,
'
event
'
,
'
lastInitial
'
]
as
const
;
const
directDrawFields
=
[
'
name
'
,
'
event
'
,
'
lastInitial
'
]
as
const
;
for
(
const
field
of
directDrawFields
)
{
for
(
const
field
of
directDrawFields
)
{
if
(
!
dto
[
field
])
continue
;
if
(
!
dto
[
field
])
continue
;
...
@@ -38,6 +39,7 @@ export class AppService extends ConsoleLogger {
...
@@ -38,6 +39,7 @@ export class AppService extends ConsoleLogger {
Coordinates
[
field
],
Coordinates
[
field
],
);
);
}
}
this
.
log
(
`Filled direct draw fields.`
);
if
(
dto
.
date
)
{
if
(
dto
.
date
)
{
const
date
=
moment
(
dto
.
date
);
const
date
=
moment
(
dto
.
date
);
// we need a dd-mm-yy format
// we need a dd-mm-yy format
...
@@ -61,6 +63,7 @@ export class AppService extends ConsoleLogger {
...
@@ -61,6 +63,7 @@ export class AppService extends ConsoleLogger {
moveRight
(
Coordinates
.
dateFirst
,
i
),
moveRight
(
Coordinates
.
dateFirst
,
i
),
);
);
}
}
this
.
log
(
`Filled date field.`
);
}
}
const
totalCounts
=
[
ydk
.
main
.
length
,
ydk
.
extra
.
length
,
ydk
.
side
.
length
];
const
totalCounts
=
[
ydk
.
main
.
length
,
ydk
.
extra
.
length
,
ydk
.
side
.
length
];
...
@@ -73,6 +76,8 @@ export class AppService extends ConsoleLogger {
...
@@ -73,6 +76,8 @@ export class AppService extends ConsoleLogger {
);
);
}
}
this
.
log
(
`Filled total counts.`
);
const
copyFirstPageToBottom
=
async
()
=>
{
const
copyFirstPageToBottom
=
async
()
=>
{
const
[
newPage
]
=
await
doc
.
copyPages
(
doc
,
[
0
]);
const
[
newPage
]
=
await
doc
.
copyPages
(
doc
,
[
0
]);
doc
.
addPage
(
newPage
);
doc
.
addPage
(
newPage
);
...
@@ -87,6 +92,7 @@ export class AppService extends ConsoleLogger {
...
@@ -87,6 +92,7 @@ export class AppService extends ConsoleLogger {
const
addCount
=
pc
-
pageCount
;
const
addCount
=
pc
-
pageCount
;
for
(
let
i
=
0
;
i
<
addCount
;
++
i
)
{
for
(
let
i
=
0
;
i
<
addCount
;
++
i
)
{
await
copyFirstPageToBottom
();
await
copyFirstPageToBottom
();
this
.
log
(
`Added page
${
pageCount
+
i
+
1
}
to PDF for deck export.`
);
}
}
pageCount
=
pc
;
pageCount
=
pc
;
};
};
...
@@ -138,14 +144,22 @@ export class AppService extends ConsoleLogger {
...
@@ -138,14 +144,22 @@ export class AppService extends ConsoleLogger {
const
filterType
=
(
type
:
number
)
=>
const
filterType
=
(
type
:
number
)
=>
ydk
.
main
.
filter
((
id
)
=>
cardDataMap
[
id
].
type
===
type
);
ydk
.
main
.
filter
((
id
)
=>
cardDataMap
[
id
].
type
===
type
);
await
drawCards
(
filterType
(
1
),
Coordinates
.
main
.
monsters
);
await
drawCards
(
filterType
(
1
),
Coordinates
.
main
.
monsters
);
this
.
log
(
`Filled monster cards.`
);
await
drawCards
(
filterType
(
2
),
Coordinates
.
main
.
spells
);
await
drawCards
(
filterType
(
2
),
Coordinates
.
main
.
spells
);
this
.
log
(
`Filled spell cards.`
);
await
drawCards
(
filterType
(
4
),
Coordinates
.
main
.
traps
);
await
drawCards
(
filterType
(
4
),
Coordinates
.
main
.
traps
);
this
.
log
(
`Filled trap cards.`
);
await
drawCards
(
ydk
.
extra
,
Coordinates
.
extra
,
15
);
await
drawCards
(
ydk
.
extra
,
Coordinates
.
extra
,
15
);
this
.
log
(
`Filled extra deck cards.`
);
await
drawCards
(
ydk
.
side
,
Coordinates
.
side
,
15
);
await
drawCards
(
ydk
.
side
,
Coordinates
.
side
,
15
);
this
.
log
(
`Filled side deck cards.`
);
doc
.
removePage
(
0
);
doc
.
removePage
(
0
);
return
new
StreamableFile
(
Buffer
.
from
(
await
doc
.
save
()),
{
const
resBuf
=
Buffer
.
from
(
await
doc
.
save
());
this
.
log
(
`Generated PDF buffer for deck export.`
);
return
new
StreamableFile
(
resBuf
,
{
type
:
'
application/pdf
'
,
type
:
'
application/pdf
'
,
disposition
:
`attachment; filename="deck_
${
Date
.
now
()}
.pdf"`
,
disposition
:
`attachment; filename="deck_
${
Date
.
now
()}
.pdf"`
,
});
});
...
...
src/card-data/card-data.service.ts
View file @
8f62bc29
...
@@ -6,6 +6,7 @@ import { CacheKey, CacheTTL } from 'aragami';
...
@@ -6,6 +6,7 @@ import { CacheKey, CacheTTL } from 'aragami';
import
{
lastValueFrom
}
from
'
rxjs
'
;
import
{
lastValueFrom
}
from
'
rxjs
'
;
import
BetterLock
from
'
better-lock
'
;
import
BetterLock
from
'
better-lock
'
;
import
{
GenericReturnMessageDto
}
from
'
nesties
'
;
import
{
GenericReturnMessageDto
}
from
'
nesties
'
;
import
*
as
fs
from
'
node:fs
'
;
@
CacheTTL
(
86400
*
30
)
@
CacheTTL
(
86400
*
30
)
export
class
CardData
{
export
class
CardData
{
...
@@ -19,6 +20,13 @@ export class CardData {
...
@@ -19,6 +20,13 @@ export class CardData {
type
:
number
;
// 0x1 for monster, 0x2 for spell, 0x4 for trap
type
:
number
;
// 0x1 for monster, 0x2 for spell, 0x4 for trap
}
}
type
YGOCDBData
=
{
id
:
number
;
sc_name
:
string
;
cn_name
:
string
;
data
:
{
type
:
number
};
};
@
Injectable
()
@
Injectable
()
export
class
CardDataService
{
export
class
CardDataService
{
constructor
(
constructor
(
...
@@ -28,15 +36,20 @@ export class CardDataService {
...
@@ -28,15 +36,20 @@ export class CardDataService {
private
logger
=
new
ConsoleLogger
(
'
CardDataService
'
);
private
logger
=
new
ConsoleLogger
(
'
CardDataService
'
);
private
async
fetchCardData
(
id
:
number
):
Promise
<
CardData
>
{
private
parseYgoCardType
(
card
:
YGOCDBData
)
{
// console.log(card);
const
data
=
new
CardData
();
const
data
=
new
CardData
();
data
.
id
=
id
;
if
(
!
card
.
id
||
!
card
.
data
)
return
;
data
.
id
=
card
.
id
;
data
.
name
=
card
.
sc_name
||
card
.
cn_name
||
'
未知卡片
'
;
data
.
type
=
card
.
data
.
type
&
0x7
;
return
data
;
}
private
async
fetchCardData
(
id
:
number
):
Promise
<
CardData
>
{
this
.
logger
.
log
(
`Fetching card data for ID
${
id
}
`
);
this
.
logger
.
log
(
`Fetching card data for ID
${
id
}
`
);
const
{
data
:
resp
,
status
}
=
await
lastValueFrom
(
const
{
data
:
resp
,
status
}
=
await
lastValueFrom
(
this
.
http
.
get
<
{
this
.
http
.
get
<
YGOCDBData
>
(
'
https://ygocdb.com/api/v0/card/
'
+
id
,
{
sc_name
:
string
;
data
:
{
type
:
number
};
}
>
(
'
https://ygocdb.com/api/v0/card/
'
+
id
,
{
timeout
:
30000
,
timeout
:
30000
,
params
:
{
params
:
{
show
:
'
all
'
,
show
:
'
all
'
,
...
@@ -51,8 +64,7 @@ export class CardDataService {
...
@@ -51,8 +64,7 @@ export class CardDataService {
`Card ID
${
id
}
not found`
,
`Card ID
${
id
}
not found`
,
).
toException
();
).
toException
();
}
}
data
.
name
=
resp
.
sc_name
;
const
data
=
this
.
parseYgoCardType
(
resp
);
data
.
type
=
resp
.
data
.
type
&
0x7
;
this
.
logger
.
log
(
this
.
logger
.
log
(
`Fetched card data for ID
${
id
}
:
${
data
.
type
}
${
data
.
name
}
`
,
`Fetched card data for ID
${
id
}
:
${
data
.
type
}
${
data
.
name
}
`
,
);
);
...
@@ -61,7 +73,36 @@ export class CardDataService {
...
@@ -61,7 +73,36 @@ export class CardDataService {
private
cardIdLock
=
new
BetterLock
();
private
cardIdLock
=
new
BetterLock
();
private
ygocdbExisting
=
new
Map
<
number
,
CardData
>
();
async
loadYGOCDBData
()
{
const
content
=
await
fs
.
promises
.
readFile
(
'
./ygocdb-data/cards.json
'
);
const
cards
:
YGOCDBData
[]
=
Object
.
values
(
JSON
.
parse
(
content
.
toString
(
'
utf-8
'
)),
);
this
.
logger
.
log
(
`Loading
${
cards
.
length
}
cards from YGOCDB data`
);
this
.
ygocdbExisting
.
clear
();
for
(
const
card
of
cards
)
{
const
data
=
this
.
parseYgoCardType
(
card
);
this
.
ygocdbExisting
.
set
(
card
.
id
,
data
);
}
}
async
onApplicationBootstrap
()
{
try
{
await
this
.
loadYGOCDBData
();
this
.
logger
.
log
(
`Loaded
${
this
.
ygocdbExisting
.
size
}
cards from YGOCDB data`
,
);
}
catch
(
e
)
{
this
.
logger
.
warn
(
`Failed to load YGOCDB data:
${
e
.
message
}
`
);
}
}
async
getCardData
(
id
:
number
):
Promise
<
CardData
>
{
async
getCardData
(
id
:
number
):
Promise
<
CardData
>
{
if
(
this
.
ygocdbExisting
.
has
(
id
))
{
return
this
.
ygocdbExisting
.
get
(
id
);
}
return
this
.
cardIdLock
.
acquire
(
id
.
toString
(),
()
=>
return
this
.
cardIdLock
.
acquire
(
id
.
toString
(),
()
=>
this
.
aragami
.
cache
(
CardData
,
id
.
toString
(),
()
=>
this
.
fetchCardData
(
id
)),
this
.
aragami
.
cache
(
CardData
,
id
.
toString
(),
()
=>
this
.
fetchCardData
(
id
)),
);
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment