Merge branch 'develop' into wip/rect_rework
This commit is contained in:
commit
6cbb15dc69
6 changed files with 136 additions and 12 deletions
|
@ -3,7 +3,7 @@ import random
|
||||||
import re
|
import re
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any, Self, Sequence, TypeVar
|
from typing import Any, Iterable, Self, Sequence, TypeVar
|
||||||
|
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
@ -32,6 +32,53 @@ def set_len(seq: Sequence[T], len: int) -> Sequence[T]:
|
||||||
return list(itertools.islice(infinite, len))
|
return list(itertools.islice(infinite, len))
|
||||||
|
|
||||||
|
|
||||||
|
def spread(
|
||||||
|
given: Iterable[int],
|
||||||
|
n: int,
|
||||||
|
rnd: Random | None = None,
|
||||||
|
) -> list[int]:
|
||||||
|
"""
|
||||||
|
Zu `given` ganzen Zahlen `n` zusätzliche Zahlen hinzunehmen.
|
||||||
|
|
||||||
|
- Die neuen Werte sind im selben Zahlenbereich wie `given`
|
||||||
|
- Zuerst werden alle Werte "zwischen" den `given` Werten genommen
|
||||||
|
"""
|
||||||
|
|
||||||
|
if n == 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if len(set(given)) > 1:
|
||||||
|
range_given = range(min(given), max(given) + 1)
|
||||||
|
first_round = set(range_given) - set(given)
|
||||||
|
|
||||||
|
elif len(set(given)) == 1:
|
||||||
|
if (a := next(iter(given))) > 0:
|
||||||
|
range_given = range(1, a + 1)
|
||||||
|
else:
|
||||||
|
range_given = range(1, n + 1)
|
||||||
|
|
||||||
|
first_round = set(range_given) - set(given)
|
||||||
|
|
||||||
|
else:
|
||||||
|
range_given = range(1, n + 1)
|
||||||
|
first_round = range_given
|
||||||
|
|
||||||
|
result = sorted(first_round)[: min(n, len(first_round))]
|
||||||
|
|
||||||
|
full_rounds = (n - len(result)) // len(range_given)
|
||||||
|
result += list(range_given) * full_rounds
|
||||||
|
|
||||||
|
remain = n - len(result)
|
||||||
|
if rnd is None:
|
||||||
|
result += list(range_given)[:remain]
|
||||||
|
|
||||||
|
else:
|
||||||
|
result += rnd.sample(range_given, remain)
|
||||||
|
rnd.shuffle(result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def list_images_auto() -> list[str]:
|
async def list_images_auto() -> list[str]:
|
||||||
"""
|
"""
|
||||||
Finde alle Bilddateien im "automatisch"-Verzeichnis
|
Finde alle Bilddateien im "automatisch"-Verzeichnis
|
||||||
|
|
77
api/test/test_spread.py
Normal file
77
api/test/test_spread.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
from advent22_api.core.helpers import spread
|
||||||
|
|
||||||
|
|
||||||
|
def test_easy() -> None:
|
||||||
|
assert spread([1, 4], 0) == []
|
||||||
|
assert spread([1, 4], 1) == [2]
|
||||||
|
assert spread([1, 4], 2) == [2, 3]
|
||||||
|
assert spread([1, 4], 5) == [2, 3, 1, 2, 3]
|
||||||
|
assert spread([1, 4], 10) == [2, 3, 1, 2, 3, 4, 1, 2, 3, 4]
|
||||||
|
|
||||||
|
|
||||||
|
def test_tight() -> None:
|
||||||
|
assert spread([1, 2], 0) == []
|
||||||
|
assert spread([1, 2], 1) == [1]
|
||||||
|
assert spread([1, 2], 2) == [1, 2]
|
||||||
|
assert spread([1, 2], 5) == [1, 2, 1, 2, 1]
|
||||||
|
assert spread([1, 2], 10) == [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
|
||||||
|
|
||||||
|
assert spread([1, 2, 3, 4, 5], 0) == []
|
||||||
|
assert spread([1, 2, 3, 4, 5], 1) == [1]
|
||||||
|
assert spread([1, 2, 3, 4, 5], 2) == [1, 2]
|
||||||
|
assert spread([1, 2, 3, 4, 5], 5) == [1, 2, 3, 4, 5]
|
||||||
|
assert spread([1, 2, 3, 4, 5], 10) == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
|
||||||
|
def test_more_given() -> None:
|
||||||
|
assert spread([0, 5, 10], 0) == []
|
||||||
|
assert spread([0, 5, 10], 1) == [1]
|
||||||
|
assert spread([0, 5, 10], 2) == [1, 2]
|
||||||
|
assert spread([0, 5, 10], 5) == [1, 2, 3, 4, 6]
|
||||||
|
assert spread([0, 5, 10], 10) == [1, 2, 3, 4, 6, 7, 8, 9, 0, 1]
|
||||||
|
|
||||||
|
assert spread([0, 1, 2, 5, 10], 0) == []
|
||||||
|
assert spread([0, 1, 2, 5, 10], 1) == [3]
|
||||||
|
assert spread([0, 1, 2, 5, 10], 2) == [3, 4]
|
||||||
|
assert spread([0, 1, 2, 5, 10], 5) == [3, 4, 6, 7, 8]
|
||||||
|
assert spread([0, 1, 2, 5, 10], 10) == [3, 4, 6, 7, 8, 9, 0, 1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
|
def test_one_given() -> None:
|
||||||
|
assert spread([0], 0) == []
|
||||||
|
assert spread([0], 1) == [1]
|
||||||
|
assert spread([0], 2) == [1, 2]
|
||||||
|
assert spread([0], 5) == [1, 2, 3, 4, 5]
|
||||||
|
assert spread([0], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
|
||||||
|
assert spread([1], 0) == []
|
||||||
|
assert spread([1], 1) == [1]
|
||||||
|
assert spread([1], 2) == [1, 1]
|
||||||
|
assert spread([1], 5) == [1, 1, 1, 1, 1]
|
||||||
|
assert spread([1], 10) == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
|
||||||
|
assert spread([2], 0) == []
|
||||||
|
assert spread([2], 1) == [1]
|
||||||
|
assert spread([2], 2) == [1, 1]
|
||||||
|
assert spread([2], 5) == [1, 1, 2, 1, 2]
|
||||||
|
assert spread([2], 10) == [1, 1, 2, 1, 2, 1, 2, 1, 2, 1]
|
||||||
|
|
||||||
|
assert spread([5], 0) == []
|
||||||
|
assert spread([5], 1) == [1]
|
||||||
|
assert spread([5], 2) == [1, 2]
|
||||||
|
assert spread([5], 5) == [1, 2, 3, 4, 1]
|
||||||
|
assert spread([5], 10) == [1, 2, 3, 4, 1, 2, 3, 4, 5, 1]
|
||||||
|
|
||||||
|
assert spread([10], 0) == []
|
||||||
|
assert spread([10], 1) == [1]
|
||||||
|
assert spread([10], 2) == [1, 2]
|
||||||
|
assert spread([10], 5) == [1, 2, 3, 4, 5]
|
||||||
|
assert spread([10], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_none_given() -> None:
|
||||||
|
assert spread([], 0) == []
|
||||||
|
assert spread([], 1) == [1]
|
||||||
|
assert spread([], 2) == [1, 2]
|
||||||
|
assert spread([], 5) == [1, 2, 3, 4, 5]
|
||||||
|
assert spread([], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
@ -23,10 +23,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<AdminButton
|
<AdminButton class="tag is-link is-outlined" v-model="is_admin" />
|
||||||
v-model="is_admin"
|
|
||||||
button_class="tag is-link is-outlined"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<LoginModal v-if="modal_visible" @submit="on_submit" @cancel="on_cancel" />
|
<LoginModal v-if="modal_visible" @submit="on_submit" @cancel="on_cancel" />
|
||||||
|
|
||||||
<BulmaButton
|
<BulmaButton
|
||||||
:class="button_class"
|
v-bind="$attrs"
|
||||||
:icon="'fa-solid fa-toggle-' + (modelValue ? 'on' : 'off')"
|
:icon="'fa-solid fa-toggle-' + (modelValue ? 'on' : 'off')"
|
||||||
:busy="is_busy"
|
:busy="is_busy"
|
||||||
text="Admin"
|
text="Admin"
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { Credentials } from "@/lib/api";
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
|
|
||||||
import BulmaButton from "./bulma/Button.vue";
|
import BulmaButton from "./bulma/Button.vue";
|
||||||
|
@ -23,14 +24,12 @@ import LoginModal from "./LoginModal.vue";
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: Boolean,
|
modelValue: Boolean,
|
||||||
button_class: String,
|
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
})
|
})
|
||||||
export default class extends Vue {
|
export default class extends Vue {
|
||||||
// true, iff Benutzer Admin ist
|
// true, iff Benutzer Admin ist
|
||||||
public modelValue!: boolean;
|
public modelValue!: boolean;
|
||||||
public button_class!: string;
|
|
||||||
|
|
||||||
public modal_visible = false;
|
public modal_visible = false;
|
||||||
public is_busy = false;
|
public is_busy = false;
|
||||||
|
@ -38,7 +37,7 @@ export default class extends Vue {
|
||||||
public on_click() {
|
public on_click() {
|
||||||
if (this.modelValue) {
|
if (this.modelValue) {
|
||||||
// logout
|
// logout
|
||||||
this.$advent22.set_api_auth();
|
this.$advent22.clear_api_auth();
|
||||||
this.$emit("update:modelValue", false);
|
this.$emit("update:modelValue", false);
|
||||||
} else {
|
} else {
|
||||||
// show login modal
|
// show login modal
|
||||||
|
@ -47,9 +46,9 @@ export default class extends Vue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public on_submit(username: string, password: string) {
|
public on_submit(creds: Credentials) {
|
||||||
this.modal_visible = false;
|
this.modal_visible = false;
|
||||||
this.$advent22.api_auth = [username, password];
|
this.$advent22.api_auth = creds;
|
||||||
|
|
||||||
this.$advent22
|
this.$advent22
|
||||||
.api_get<boolean>("admin/is_admin")
|
.api_get<boolean>("admin/is_admin")
|
||||||
|
|
|
@ -89,7 +89,7 @@ export default class extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
public submit(): void {
|
public submit(): void {
|
||||||
this.$emit("submit", this.username, this.password);
|
this.$emit("submit", [this.username, this.password]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public cancel(): void {
|
public cancel(): void {
|
||||||
|
|
|
@ -94,6 +94,10 @@ export class Advent22 {
|
||||||
this._api_auth = creds;
|
this._api_auth = creds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear_api_auth(): void {
|
||||||
|
this.set_api_auth();
|
||||||
|
}
|
||||||
|
|
||||||
public set api_auth(creds: Credentials) {
|
public set api_auth(creds: Credentials) {
|
||||||
this.set_api_auth(creds);
|
this.set_api_auth(creds);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue