Skip to content

Commit 98351ab

Browse files
feat!: 157 daily problem design (#158)
* feat: bazel cpp dynamic dynamic load daily * fix: daily * feat: cpp bazel plans loaded from daily json * feat: cpp bazel plans daily plans * feat: java dynamic problem load from daily * feat: add problems folder folder after plan problem * feat: python dynamic load * feat: typescript dynamic load * refactor: update README instructions for daily and plans in multiple languages * feat: clean up test file handling in language writers * feat: update workflow * test: [20250611] Add (3445) --------- Co-authored-by: GitHub Action <[email protected]>
1 parent ad2c53d commit 98351ab

26 files changed

+446
-274
lines changed

.github/workflows/daily.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
data
3434
${{ secrets.PROBLEM_FOLDER || 'problems' }}
3535
${{ secrets.PREMIUM_FOLDER || 'premiums' }}
36+
daily-${{ secrets.PROBLEM_FOLDER || 'problems' }}.json
3637
3738
- name: Set up Python environment
3839
uses: actions/setup-python@v2

.github/workflows/daily_check.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
data
3434
${{ secrets.PROBLEM_FOLDER || 'problems' }}
3535
${{ secrets.PREMIUM_FOLDER || 'premiums' }}
36+
daily-${{ secrets.PROBLEM_FOLDER || 'problems' }}.json
3637
3738
- name: Set up Python environment
3839
uses: actions/setup-python@v2

BUILD

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
load("//:solutions.bzl", "generate_cc_tests")
22

3-
generate_cc_tests()
3+
generate_cc_tests(enabled = False)
4+
5+
load("@plans//:plans.bzl", "PLANS")
6+
load("//:solutions.bzl", "gen_plans")
7+
8+
gen_plans(plans = PLANS)

MODULE.bazel

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
module(name = "cpp")
2+
13
# Hedron's Compile Commands Extractor for Bazel
24
# https://github.com/hedronvision/bazel-compile-commands-extractor
35
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)
@@ -12,16 +14,9 @@ git_override(
1214
bazel_dep(name = "googletest", version = "1.17.0")
1315
bazel_dep(name = "nlohmann_json", version = "3.12.0")
1416

15-
new_local_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:local.bzl", "new_local_repository")
1617

17-
new_local_repository(
18-
name = "problems",
19-
build_file = "//cpp:solution.BUILD",
20-
path = "problems/problems_3445/",
21-
)
18+
load_daily_question = use_extension("//:extensions.bzl", "load_daily_question")
19+
use_repo(load_daily_question, "problems")
2220

23-
new_local_repository(
24-
name = "problem0",
25-
path = "problems/problems_LCR_115/",
26-
build_file = "//cpp:solution.BUILD",
27-
)
21+
daily_plans = use_repo_rule("//:extensions.bzl", "daily_plans")
22+
daily_plans(name = "plans")

cpp/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44

55
First install bazel environment,
66

7-
**change path of problem ` path = "problems/problems_2028/",` in [BAZEL MODULE](../MODULE.bazel)**, and try:
7+
For daily:
8+
**change daily in [daily.json](../daily-problems.json)** `Note: the json file is under root with your problem folder, named 'daily-${folder}.json'` and try:
89
```shell
910
bazel test --cxxopt=-std=c++23 --cxxopt=-O2 --cxxopt=-fsanitize=address --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1 --linkopt=-fsanitize=address --test_timeout=3 --test_output=all //cpp:solution_test
1011
```
1112

12-
or if you want to run more than one questions,
13-
**change problem and path in `new_local_repository(name = "problem0", path = "problems/problems_1/"` in [MODULE](../MODULE.bazel)** and maybe add the name ref `@problem0` in [BUILD](tests/BUILD), and try:
13+
or for multiple problems from plans,
14+
**change plans in [daily.json](../daily-problems.json)** `Note: the json file is under root with your problem folder, named 'daily-${folder}.json'` and try:
1415
```shell
15-
bazel test --cxxopt=-std=c++23 --cxxopt=-O2 --cxxopt=-fsanitize=address --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1 --linkopt=-fsanitize=address --test_timeout=10 --test_output=all //cpp/tests:all
16+
bazel test --cxxopt=-std=c++23 --cxxopt=-O2 --cxxopt=-fsanitize=address --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=1 --linkopt=-fsanitize=address --test_timeout=10 --test_output=all //:all
1617
```
1718

1819
## Environment setup for idea:
19-
First Change the path of the problem in the [solutions.bzl](../solutions.bzl) file
20+
21+
change line `generate_cc_tests(enabled = False)` to `generate_cc_tests(enabled = True)` in [BUILD](../BUILD)
2022

2123
[bazel-compile-commands-extractor](https://github.com/hedronvision/bazel-compile-commands-extractor)
2224
```shell

cpp/tests/BUILD

Lines changed: 0 additions & 21 deletions
This file was deleted.

daily-problems.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"daily": "3445",
3+
"plans": ["1", "problems", "LCR_115", "problems"]
4+
}

extensions.bzl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
## extensions.bzl
2+
load("@bazel_tools//tools/build_defs/repo:local.bzl", "new_local_repository")
3+
4+
def _format_path(folder, problem):
5+
"""Format the path for a problem."""
6+
return "%s/%s_%s/" % (folder, folder, problem)
7+
8+
def _load_daily_question_impl(ctx):
9+
script = ctx.path(Label("//:get_daily_path.py"))
10+
root = ctx.path(Label("//:MODULE.bazel")).dirname
11+
result = ctx.execute([ctx.which("python3"), script, root])
12+
if result.return_code != 0:
13+
fail("Failed to get daily problem path: %s" % result.stderr)
14+
# result in three lines
15+
s = result.stdout.strip()
16+
splits = s.splitlines()
17+
if len(splits) != 3:
18+
fail("Expected three lines in output, got: %s" % s)
19+
folder = splits[0]
20+
daily_problem = splits[1]
21+
new_local_repository(
22+
name = "problems",
23+
build_file = "//cpp:solution.BUILD",
24+
path = _format_path(folder, daily_problem),
25+
)
26+
27+
load_daily_question = module_extension(
28+
implementation = _load_daily_question_impl,
29+
)
30+
31+
def _impl(rctx):
32+
script = rctx.path(Label("//:get_daily_path.py"))
33+
root = rctx.path(Label("//:MODULE.bazel")).dirname
34+
result = rctx.execute([rctx.which("python3"), script, root])
35+
if result.return_code != 0:
36+
fail("Failed to get daily problem path: %s" % result.stderr)
37+
s = result.stdout.strip()
38+
splits = s.splitlines()
39+
if len(splits) != 3:
40+
fail("Expected three lines in output, got: %s" % s)
41+
plans = splits[2]
42+
rctx.file("BUILD", "exports_files([\"plans.bzl\"])\nvisibility = [\"//visibility:public\"]\n")
43+
rctx.file("plans.bzl", """\
44+
PLANS = %s
45+
""" % ("[" + ",".join(['"%s"' % p for p in plans.split(",")]) + "]"))
46+
47+
48+
daily_plans = repository_rule(
49+
implementation = _impl,
50+
)

get_daily_path.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import os, json
2+
3+
def parse_env(path):
4+
d = {}
5+
if os.path.exists(path):
6+
for line in open(path):
7+
if '=' in line and not line.strip().startswith('#'):
8+
k, v = line.strip().split('=', 1)
9+
d[k.strip()] = v.strip().strip('"').strip("'")
10+
return d
11+
12+
root = os.path.dirname(__file__)
13+
env = parse_env(os.path.join(root, ".env"))
14+
folder = env.get("PROBLEM_FOLDER", "problems")
15+
json_path = os.path.join(root, f"daily-{folder}.json")
16+
with open(json_path) as f:
17+
data_json = json.load(f)
18+
daily = data_json.get("daily", "1")
19+
plans = data_json.get("plans", [])
20+
print(folder)
21+
print(daily)
22+
print(",".join(plans))

pom.xml

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>LeetCode.qubhjava</groupId>
66
<artifactId>qubhjava</artifactId>
7-
<version>1.0.0</version>
7+
<version>2.0.0</version>
88
<properties>
99
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1010
<maven.compiler.release>21</maven.compiler.release>
@@ -68,6 +68,107 @@
6868
</dependencies>
6969
<build>
7070
<plugins>
71+
72+
<!-- Groovy脚本执行器 -->
73+
<plugin>
74+
<groupId>org.codehaus.gmavenplus</groupId>
75+
<artifactId>gmavenplus-plugin</artifactId>
76+
<version>4.2.0</version>
77+
<dependencies>
78+
<dependency>
79+
<groupId>org.codehaus.groovy</groupId>
80+
<artifactId>groovy-all</artifactId>
81+
<version>3.0.25</version>
82+
<type>pom</type>
83+
</dependency>
84+
</dependencies>
85+
<executions>
86+
<execution>
87+
<id>parse-config</id>
88+
<phase>initialize</phase>
89+
<goals>
90+
<goal>execute</goal>
91+
</goals>
92+
<configuration>
93+
<scripts>
94+
<script><![CDATA[
95+
import groovy.json.JsonSlurper
96+
import java.nio.file.*
97+
98+
// 1. 读取.env文件
99+
def envFile = new File("${project.basedir}/.env")
100+
def baseDir = "problems"
101+
if (envFile.exists()) {
102+
envFile.eachLine { line ->
103+
if (line.startsWith("PROBLEMS_FOLDER=")) {
104+
baseDir = line.split("=")[1].trim()
105+
}
106+
}
107+
}
108+
109+
// 2. 读取config.json
110+
def configFile = new File("${project.basedir}/daily-${baseDir}.json")
111+
if (!configFile.exists()) {
112+
throw new RuntimeException("Config file not found: ${configFile.absolutePath}")
113+
}
114+
def config = new JsonSlurper().parse(configFile)
115+
116+
// 3. 构建源目录列表
117+
def sources = [] as Set
118+
sources.add(new File(project.basedir, "${baseDir}/${baseDir}_${config.daily}/").absolutePath)
119+
for (int i = 0; i < config.plans.size(); i += 2) {
120+
def problem = config.plans[i]
121+
def folder = config.plans[i + 1]
122+
sources.add(new File(project.basedir, "${folder}/${folder}_${problem}/").absolutePath)
123+
}
124+
125+
println "==> 添加动态源目录:"
126+
sources.each { println " - $it" }
127+
128+
// 4. 设置Maven属性
129+
sources.eachWithIndex { source, index ->
130+
project.properties["dynamic.source${index + 1}"] = source
131+
}
132+
// 5. 补全10个
133+
(sources.size()..9).each { index ->
134+
project.properties["dynamic.source${index + 1}"] = "qubhjava"
135+
}
136+
]]></script>
137+
</scripts>
138+
</configuration>
139+
</execution>
140+
</executions>
141+
</plugin>
142+
<!-- 添加动态源目录插件 -->
143+
<plugin>
144+
<groupId>org.codehaus.mojo</groupId>
145+
<artifactId>build-helper-maven-plugin</artifactId>
146+
<version>3.6.1</version>
147+
<executions>
148+
<execution>
149+
<id>add-problem-sources</id>
150+
<phase>generate-sources</phase>
151+
<goals>
152+
<goal>add-source</goal>
153+
</goals>
154+
<configuration>
155+
<sources>
156+
<source>${dynamic.source1}</source>
157+
<source>${dynamic.source2}</source>
158+
<source>${dynamic.source3}</source>
159+
<source>${dynamic.source4}</source>
160+
<source>${dynamic.source5}</source>
161+
<source>${dynamic.source6}</source>
162+
<source>${dynamic.source7}</source>
163+
<source>${dynamic.source8}</source>
164+
<source>${dynamic.source9}</source>
165+
<source>${dynamic.source10}</source>
166+
</sources>
167+
</configuration>
168+
</execution>
169+
</executions>
170+
</plugin>
171+
71172
<plugin>
72173
<groupId>org.apache.maven.plugins</groupId>
73174
<artifactId>maven-surefire-plugin</artifactId>
@@ -92,7 +193,7 @@
92193
</configuration>
93194
</plugin>
94195
</plugins>
95-
<sourceDirectory>.</sourceDirectory>
196+
<sourceDirectory>qubhjava</sourceDirectory>
96197
<testSourceDirectory>qubhjava/test</testSourceDirectory>
97198
</build>
98199
</project>

0 commit comments

Comments
 (0)