From 3170e1abd5558039811f80031727f43eb07e8294 Mon Sep 17 00:00:00 2001 From: OBrutus Date: Sat, 13 Jun 2026 23:36:30 +0530 Subject: [PATCH] feat: implement AtCoder platform support with URL extraction and testing --- src/platform/atcoder/atcoder.go | 76 ++++++++++++++++++++++++++++ src/platform/atcoder/atcoder_test.go | 35 +++++++++++++ src/platform/identifier.go | 3 ++ 3 files changed, 114 insertions(+) create mode 100644 src/platform/atcoder/atcoder.go create mode 100644 src/platform/atcoder/atcoder_test.go diff --git a/src/platform/atcoder/atcoder.go b/src/platform/atcoder/atcoder.go new file mode 100644 index 0000000..54d8c32 --- /dev/null +++ b/src/platform/atcoder/atcoder.go @@ -0,0 +1,76 @@ +package atcoder + +import ( + "errors" + "prepare-code/src/constants" + "prepare-code/src/types" + "strings" +) + +var ErrInvalidAtCoderUrl = errors.New("invalid url of AtCoder") + +const urlFormat string = "https://atcoder.jp/contests/abc461/tasks/abc461_a" + +const codeNameDelimiter string = "-" + +type AtCoderPlatform struct { + name types.PlatformName + codeName string +} + +func (ac AtCoderPlatform) GetPlatformName() types.PlatformName { + return constants.PlatformAtCoder +} + +func (ac AtCoderPlatform) GetCodeName() string { + return ac.codeName +} + +func (ac AtCoderPlatform) GetPlatform(url string) (types.Platform, error) { + return GetPlatform(url) +} + +// This is the main method +func GetPlatform(url string) (types.Platform, error) { + extractedCodeName, err := extractCodeName(url) + if err != nil { + return nil, err + } + + return AtCoderPlatform{ + name: constants.PlatformCodeforces, + codeName: extractedCodeName, // placeholder for actual extraction logic + }, nil +} + +func extractCodeName(url string) (string, error) { + // https://atcoder.jp/contests/abc461/tasks/abc461_a + if len(url) < len("atcoder.jp") { + return "", ErrInvalidAtCoderUrl + } + + i := 0 + const prefix string = "atcoder.jp/contests/" + for i+len(prefix) < len(url) { + if url[i:i+len(prefix)] == prefix { + break + } + i++ + } + + i += len(prefix) + if i == len(url) { + return "", ErrInvalidAtCoderUrl + } + + prefixRemovedString := url[i:] + suffix := strings.Split(prefixRemovedString, "/") + if len(suffix) < 3 { + return "", ErrInvalidAtCoderUrl + } + + // contestNumber := suffix[0] + qeustionCode := strings.ToUpper(suffix[2]) + + return qeustionCode, nil +} diff --git a/src/platform/atcoder/atcoder_test.go b/src/platform/atcoder/atcoder_test.go new file mode 100644 index 0000000..cbcdda6 --- /dev/null +++ b/src/platform/atcoder/atcoder_test.go @@ -0,0 +1,35 @@ +package atcoder + +import "testing" + +func TestSimpleCodeExtraction(t *testing.T) { + testCases := []struct { + name string + url string + code string + err error + }{ + {name: "Positive Test Case", url: "https://atcoder.jp/contests/abc461/tasks/abc461_a", code: "ABC461_A", err: nil}, + {name: "Test Case 1", url: "https://atcoder.jp/contests/abc461/tasks/", err: ErrInvalidAtCoderUrl}, + {name: "Test Case 2", url: "https://atcoder.jp/contests/abc461/tasks", err: ErrInvalidAtCoderUrl}, + {name: "Test Case 3", url: "https://atcoder.jp/contests/abc461/", err: ErrInvalidAtCoderUrl}, + {name: "Test Case 4", url: "https://atcoder.jp/contests/abc461", err: ErrInvalidAtCoderUrl}, + {name: "Test Case 5", url: "https://atcoder.jp/contests/", err: ErrInvalidAtCoderUrl}, + {name: "Test Case 6", url: "https://atcoder/contests/", err: ErrInvalidAtCoderUrl}, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + code, err := extractCodeName(tt.url) + if (err != nil && tt.err != nil) && err != tt.err { + t.Errorf("Test Failed for %s. Got=%v Expected=%v", tt.name, err, tt.err) + return + } + + if code != tt.code { + t.Errorf("Test Failed for %s. Got=%v Expected=%v", tt.name, code, tt.code) + return + } + }) + } +} diff --git a/src/platform/identifier.go b/src/platform/identifier.go index 5e9a91d..fbb8a47 100644 --- a/src/platform/identifier.go +++ b/src/platform/identifier.go @@ -2,6 +2,7 @@ package platform import ( "errors" + "prepare-code/src/platform/atcoder" "prepare-code/src/platform/codeforces" "prepare-code/src/platform/leetcode" "prepare-code/src/types" @@ -20,6 +21,8 @@ func GetPlatform(url string) (types.Platform, error) { return codeforces.GetPlatform(url) } else if strings.Contains(url, "leetcode.com") { return leetcode.GetPlatform(url) + } else if strings.Contains(url, "atcoder.jp") { + return atcoder.GetPlatform(url) } else { return nil, errors.New("unknown platform or platform not supported") }