Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-deck-encode
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-deck-encode
Commits
2c6d6fc6
Commit
2c6d6fc6
authored
May 21, 2025
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add ydke and update doc
parent
439c6df1
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
169 additions
and
13 deletions
+169
-13
README.md
README.md
+8
-0
index.ts
index.ts
+28
-7
package-lock.json
package-lock.json
+9
-1
package.json
package.json
+2
-1
src/ydke.ts
src/ydke.ts
+60
-0
src/ygom.ts
src/ygom.ts
+2
-2
tests/sample.spec.ts
tests/sample.spec.ts
+23
-2
tests/ydke.spec.ts
tests/ydke.spec.ts
+37
-0
No files found.
README.md
View file @
2c6d6fc6
...
@@ -15,6 +15,14 @@ const anotherDeck = YGOProDeck.fromEncodedString(code); // decode it back
...
@@ -15,6 +15,14 @@ const anotherDeck = YGOProDeck.fromEncodedString(code); // decode it back
const
ydk
=
deck
.
toYdkString
();
// YDK format
const
ydk
=
deck
.
toYdkString
();
// YDK format
const
yetAnotherDeck
=
YGOProDeck
.
fromYdkString
(
ydk
);
// decode it back
const
yetAnotherDeck
=
YGOProDeck
.
fromYdkString
(
ydk
);
// decode it back
const
ydke
=
deck
.
toYdkeURL
();
const
yetAnotherDeck2
=
YGOProDeck
.
fromYdkeURL
(
ydke
);
// decode it back
const
ygomobileDeckUrl
=
deck
.
toYGOMobileDeckURL
();
// YGOMobile Deck URL
const
yetAnotherDeck3
=
YGOProDeck
.
fromYGOMobileDeckURL
(
ygomobileDeckUrl
);
// decode it back
const
updateDeckPayload
=
deck
.
toUpdateDeckPayload
();
// payload for MSG_UPDATE_DECK
```
```
...
...
index.ts
View file @
2c6d6fc6
import
{
fromBase64Url
,
toBase64Url
}
from
'
./src/base64
'
;
import
{
fromBase64Url
,
toBase64Url
}
from
'
./src/base64
'
;
import
{
BufferWriter
,
countItems
}
from
'
./src/utils
'
;
import
{
BufferWriter
,
countItems
}
from
'
./src/utils
'
;
import
{
fromYGOMobileDeckUri
,
toYGOMobileDeckUri
}
from
'
./src/ygom
'
;
import
{
fromYdkeURL
,
toYdkeURL
}
from
'
./src/ydke
'
;
import
{
fromYGOMobileDeckURL
,
toYGOMobileDeckURL
}
from
'
./src/ygom
'
;
export
default
class
YGOProDeck
{
export
default
class
YGOProDeck
{
main
:
number
[]
=
[];
main
:
number
[]
=
[];
...
@@ -113,8 +114,8 @@ export default class YGOProDeck {
...
@@ -113,8 +114,8 @@ export default class YGOProDeck {
return
writer
.
buffer
;
return
writer
.
buffer
;
}
}
fromYGOMobileDeckU
ri
(
uri
:
string
):
YGOProDeck
{
fromYGOMobileDeckU
RL
(
uri
:
string
):
YGOProDeck
{
const
parsed
=
fromYGOMobileDeckU
ri
(
uri
);
const
parsed
=
fromYGOMobileDeckU
RL
(
uri
);
this
.
main
=
parsed
.
main
;
this
.
main
=
parsed
.
main
;
this
.
extra
=
parsed
.
extra
;
this
.
extra
=
parsed
.
extra
;
this
.
side
=
parsed
.
side
;
this
.
side
=
parsed
.
side
;
...
@@ -122,13 +123,33 @@ export default class YGOProDeck {
...
@@ -122,13 +123,33 @@ export default class YGOProDeck {
return
this
;
return
this
;
}
}
static
fromYGOMobileDeckU
ri
(
uri
:
string
):
YGOProDeck
{
static
fromYGOMobileDeckU
RL
(
uri
:
string
):
YGOProDeck
{
return
new
YGOProDeck
().
fromYGOMobileDeckU
ri
(
uri
);
return
new
YGOProDeck
().
fromYGOMobileDeckU
RL
(
uri
);
}
}
toYGOMobileDeckU
ri
():
string
{
toYGOMobileDeckU
RL
():
string
{
return
toYGOMobileDeckU
ri
(
this
.
main
,
this
.
extra
,
this
.
side
,
this
.
name
&&
{
return
toYGOMobileDeckU
RL
(
this
.
main
,
this
.
extra
,
this
.
side
,
this
.
name
&&
{
name
:
this
.
name
,
name
:
this
.
name
,
});
});
}
}
fromYdkeURL
(
uri
:
string
):
YGOProDeck
{
const
parsed
=
fromYdkeURL
(
uri
);
this
.
main
=
parsed
.
main
;
this
.
extra
=
parsed
.
extra
;
this
.
side
=
parsed
.
side
;
return
this
;
}
static
fromYdkeURL
(
uri
:
string
):
YGOProDeck
{
return
new
YGOProDeck
().
fromYdkeURL
(
uri
);
}
toYdkeURL
():
string
{
return
toYdkeURL
({
main
:
this
.
main
,
extra
:
this
.
extra
,
side
:
this
.
side
,
});
}
}
}
package-lock.json
View file @
2c6d6fc6
...
@@ -22,7 +22,8 @@
...
@@ -22,7 +22,8 @@
"prettier"
:
"^2.8.4"
,
"prettier"
:
"^2.8.4"
,
"rimraf"
:
"^4.1.2"
,
"rimraf"
:
"^4.1.2"
,
"ts-jest"
:
"^29.0.5"
,
"ts-jest"
:
"^29.0.5"
,
"typescript"
:
"^4.9.5"
"typescript"
:
"^4.9.5"
,
"ydke"
:
"^1.1.0"
}
}
},
},
"node_modules/@ampproject/remapping"
:
{
"node_modules/@ampproject/remapping"
:
{
...
@@ -5168,6 +5169,13 @@
...
@@ -5168,6 +5169,13 @@
"node"
:
">=12"
"node"
:
">=12"
}
}
},
},
"node_modules/ydke"
:
{
"version"
:
"1.1.0"
,
"resolved"
:
"https://registry.npmjs.org/ydke/-/ydke-1.1.0.tgz"
,
"integrity"
:
"sha512-q6EbAMtup1stTOER9/PNLH/uDQ1guYmiTU/+jn1BSePmkfvm9Rky49byQDNqYQjwrSXoLaoygkQMGIwNQRr+cg=="
,
"dev"
:
true
,
"license"
:
"LGPL-3.0+"
},
"node_modules/yocto-queue"
:
{
"node_modules/yocto-queue"
:
{
"version"
:
"0.1.0"
,
"version"
:
"0.1.0"
,
"resolved"
:
"https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
,
"resolved"
:
"https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
,
...
...
package.json
View file @
2c6d6fc6
...
@@ -56,6 +56,7 @@
...
@@ -56,6 +56,7 @@
"
prettier
"
:
"
^2.8.4
"
,
"
prettier
"
:
"
^2.8.4
"
,
"
rimraf
"
:
"
^4.1.2
"
,
"
rimraf
"
:
"
^4.1.2
"
,
"
ts-jest
"
:
"
^29.0.5
"
,
"
ts-jest
"
:
"
^29.0.5
"
,
"
typescript
"
:
"
^4.9.5
"
"
typescript
"
:
"
^4.9.5
"
,
"
ydke
"
:
"
^1.1.0
"
}
}
}
}
src/ydke.ts
0 → 100644
View file @
2c6d6fc6
// ydke.ts
export
interface
TypedDeck
{
main
:
number
[];
extra
:
number
[];
side
:
number
[];
}
function
base64ToUint32Array
(
base64
:
string
):
number
[]
{
const
binary
=
atob
(
base64
);
const
bytes
=
new
Uint8Array
(
binary
.
length
);
for
(
let
i
=
0
;
i
<
binary
.
length
;
i
++
)
{
bytes
[
i
]
=
binary
.
charCodeAt
(
i
);
}
const
view
=
new
DataView
(
bytes
.
buffer
);
const
result
:
number
[]
=
[];
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
+=
4
)
{
result
.
push
(
view
.
getUint32
(
i
,
true
));
// little-endian
}
return
result
;
}
function
uint32ArrayToBase64
(
data
:
number
[]):
string
{
const
buffer
=
new
ArrayBuffer
(
data
.
length
*
4
);
const
view
=
new
DataView
(
buffer
);
data
.
forEach
((
val
,
i
)
=>
view
.
setUint32
(
i
*
4
,
val
,
true
));
const
bytes
=
new
Uint8Array
(
buffer
);
let
binary
=
''
;
for
(
let
i
=
0
;
i
<
bytes
.
length
;
i
++
)
{
binary
+=
String
.
fromCharCode
(
bytes
[
i
]);
}
return
btoa
(
binary
);
}
export
function
toYdkeURL
(
deck
:
TypedDeck
):
string
{
return
(
'
ydke://
'
+
uint32ArrayToBase64
(
deck
.
main
)
+
'
!
'
+
uint32ArrayToBase64
(
deck
.
extra
)
+
'
!
'
+
uint32ArrayToBase64
(
deck
.
side
)
+
'
!
'
);
}
export
function
fromYdkeURL
(
ydke
:
string
):
TypedDeck
{
if
(
!
ydke
.
startsWith
(
'
ydke://
'
))
{
throw
new
Error
(
'
Invalid ydke:// URI
'
);
}
const
[
mainStr
,
extraStr
,
sideStr
]
=
ydke
.
slice
(
7
).
split
(
'
!
'
);
if
(
mainStr
===
undefined
||
extraStr
===
undefined
||
sideStr
===
undefined
)
{
throw
new
Error
(
'
Incomplete ydke:// URI
'
);
}
return
{
main
:
base64ToUint32Array
(
mainStr
),
extra
:
base64ToUint32Array
(
extraStr
),
side
:
base64ToUint32Array
(
sideStr
),
};
}
src/ygom.ts
View file @
2c6d6fc6
...
@@ -47,7 +47,7 @@ function countUnique(cards: number[]): number {
...
@@ -47,7 +47,7 @@ function countUnique(cards: number[]): number {
// === 主函数 ===
// === 主函数 ===
export
function
toYGOMobileDeckU
ri
(
export
function
toYGOMobileDeckU
RL
(
main
:
number
[],
main
:
number
[],
extra
:
number
[],
extra
:
number
[],
side
:
number
[],
side
:
number
[],
...
@@ -80,7 +80,7 @@ export function toYGOMobileDeckUri(
...
@@ -80,7 +80,7 @@ export function toYGOMobileDeckUri(
}
}
export
function
fromYGOMobileDeckU
ri
(
uri
:
string
):
{
export
function
fromYGOMobileDeckU
RL
(
uri
:
string
):
{
main
:
number
[];
main
:
number
[];
extra
:
number
[];
extra
:
number
[];
side
:
number
[];
side
:
number
[];
...
...
tests/sample.spec.ts
View file @
2c6d6fc6
...
@@ -54,15 +54,36 @@ describe('Sample test.', () => {
...
@@ -54,15 +54,36 @@ describe('Sample test.', () => {
it
(
'
should encode and decode ygomobile
'
,
()
=>
{
it
(
'
should encode and decode ygomobile
'
,
()
=>
{
const
uri
=
'
http://deck.ourygo.top?name=%E7%99%BD%E9%93%B6%E5%9F%8E%E7%A0%81&ygotype=deck&v=1&d=J-xK4Mka02AuEAMf2dV6mj7aRemuJNQJK8BwrcEYh0MqOJqBJSgYqUwxPEVhOG8R18WWVKmzkT-xEdwxbmGVkkOdrVIpufaYI3Hs8oOrcya8Bi40h9G79iFW80rq-o6P-AHsusPY5nmvHLol0DIqEykESVlf6VSbxVJp-j7XZtTE0XvmJW80rqH28R4rgyRovOusVJzbutenYFBA_cyK6d3UWcQkJQlLjaroWavH-INFA56k5DQNWOQ1gpvxrKVBLgEk1olpolKmSgriramLlgtBK1EQ6C6oi94ZyHe7N6T7mqE6peds7mahrORP6A
'
;
const
uri
=
'
http://deck.ourygo.top?name=%E7%99%BD%E9%93%B6%E5%9F%8E%E7%A0%81&ygotype=deck&v=1&d=J-xK4Mka02AuEAMf2dV6mj7aRemuJNQJK8BwrcEYh0MqOJqBJSgYqUwxPEVhOG8R18WWVKmzkT-xEdwxbmGVkkOdrVIpufaYI3Hs8oOrcya8Bi40h9G79iFW80rq-o6P-AHsusPY5nmvHLol0DIqEykESVlf6VSbxVJp-j7XZtTE0XvmJW80rqH28R4rgyRovOusVJzbutenYFBA_cyK6d3UWcQkJQlLjaroWavH-INFA56k5DQNWOQ1gpvxrKVBLgEk1olpolKmSgriramLlgtBK1EQ6C6oi94ZyHe7N6T7mqE6peds7mahrORP6A
'
;
const
deck
=
new
YGOProDeck
().
fromYGOMobileDeckU
ri
(
uri
);
const
deck
=
new
YGOProDeck
().
fromYGOMobileDeckU
RL
(
uri
);
expect
(
deck
.
main
).
toHaveLength
(
58
);
expect
(
deck
.
main
).
toHaveLength
(
58
);
expect
(
deck
.
extra
).
toHaveLength
(
15
);
expect
(
deck
.
extra
).
toHaveLength
(
15
);
expect
(
deck
.
side
).
toHaveLength
(
15
);
expect
(
deck
.
side
).
toHaveLength
(
15
);
expect
(
deck
.
main
[
0
]).
toBe
(
22812963
);
expect
(
deck
.
main
[
0
]).
toBe
(
22812963
);
expect
(
deck
.
extra
[
0
]).
toBe
(
12381100
);
expect
(
deck
.
extra
[
0
]).
toBe
(
12381100
);
expect
(
deck
.
side
[
0
]).
toBe
(
20292186
);
expect
(
deck
.
side
[
0
]).
toBe
(
20292186
);
const
uri2
=
deck
.
toYGOMobileDeckU
ri
();
const
uri2
=
deck
.
toYGOMobileDeckU
RL
();
expect
(
uri2
).
toBe
(
uri
);
expect
(
uri2
).
toBe
(
uri
);
})
})
it
(
'
should encode and decode ydke URL
'
,
()
=>
{
const
deck
=
new
YGOProDeck
();
deck
.
main
.
push
(
111111
);
deck
.
main
.
push
(
111111
);
deck
.
main
.
push
(
111111
);
deck
.
main
.
push
(
222222
);
deck
.
main
.
push
(
333333
);
deck
.
extra
.
push
(
444444
);
deck
.
extra
.
push
(
555555
);
deck
.
side
.
push
(
666666
);
const
uri
=
deck
.
toYdkeURL
();
expect
(
uri
.
startsWith
(
'
ydke://
'
)).
toBe
(
true
);
const
decoded
=
new
YGOProDeck
().
fromYdkeURL
(
uri
);
expect
(
decoded
.
main
).
toStrictEqual
(
deck
.
main
);
expect
(
decoded
.
extra
).
toStrictEqual
(
deck
.
extra
);
expect
(
decoded
.
side
).
toStrictEqual
(
deck
.
side
);
});
});
});
tests/ydke.spec.ts
0 → 100644
View file @
2c6d6fc6
import
YGOProDeck
from
'
..
'
;
import
*
as
ydkejs
from
'
ydke
'
;
describe
(
'
YDKE interoperability test
'
,
()
=>
{
const
main
=
[
1000
,
1000
,
1000
,
2000
,
2000
,
3000
];
const
extra
=
[
4000
,
5000
];
const
side
=
[
6000
];
it
(
'
should encode with ygopro-deck-encode and decode with ydke.js
'
,
()
=>
{
const
deck
=
new
YGOProDeck
();
deck
.
main
=
[...
main
];
deck
.
extra
=
[...
extra
];
deck
.
side
=
[...
side
];
const
uri
=
deck
.
toYdkeURL
();
const
decoded
=
ydkejs
.
parseURL
(
uri
);
expect
(
Array
.
from
(
decoded
.
main
)).
toStrictEqual
(
main
);
expect
(
Array
.
from
(
decoded
.
extra
)).
toStrictEqual
(
extra
);
expect
(
Array
.
from
(
decoded
.
side
)).
toStrictEqual
(
side
);
});
it
(
'
should encode with ydke.js and decode with ygopro-deck-encode
'
,
()
=>
{
const
typedDeck
:
ydkejs
.
TypedDeck
=
{
main
:
new
Uint32Array
(
main
),
extra
:
new
Uint32Array
(
extra
),
side
:
new
Uint32Array
(
side
),
};
const
uri
=
ydkejs
.
toURL
(
typedDeck
);
const
decoded
=
new
YGOProDeck
().
fromYdkeURL
(
uri
);
expect
(
decoded
.
main
).
toStrictEqual
(
main
);
expect
(
decoded
.
extra
).
toStrictEqual
(
extra
);
expect
(
decoded
.
side
).
toStrictEqual
(
side
);
});
});
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