summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locales/ja-JP.yml1
-rw-r--r--migration/1620364649428-ad2.ts14
-rw-r--r--src/client/components/global/ad.vue45
-rw-r--r--src/client/instance.ts8
-rw-r--r--src/client/pages/instance/ads.vue6
-rw-r--r--src/models/entities/ad.ts6
-rw-r--r--src/server/api/endpoints/admin/ad/create.ts4
-rw-r--r--src/server/api/endpoints/admin/ad/update.ts4
-rw-r--r--src/server/api/endpoints/meta.ts2
9 files changed, 72 insertions, 18 deletions
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 0f786a6b14..31b02821bf 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -756,6 +756,7 @@ high: "高"
middle: "中"
low: "低"
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
+ratio: "比率"
_forgotPassword:
enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。"
diff --git a/migration/1620364649428-ad2.ts b/migration/1620364649428-ad2.ts
new file mode 100644
index 0000000000..a2d7f563c2
--- /dev/null
+++ b/migration/1620364649428-ad2.ts
@@ -0,0 +1,14 @@
+import {MigrationInterface, QueryRunner} from "typeorm";
+
+export class ad21620364649428 implements MigrationInterface {
+ name = 'ad21620364649428'
+
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`ALTER TABLE "ad" ADD "ratio" integer NOT NULL DEFAULT '1'`);
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`);
+ }
+
+}
diff --git a/src/client/components/global/ad.vue b/src/client/components/global/ad.vue
index f88a1d2026..e340f846ee 100644
--- a/src/client/components/global/ad.vue
+++ b/src/client/components/global/ad.vue
@@ -19,7 +19,7 @@
<script lang="ts">
import { defineComponent, ref } from 'vue';
-import { instance } from '@client/instance';
+import { Instance, instance } from '@client/instance';
import { host } from '@client/config';
import MkButton from '@client/components/ui/button.vue';
@@ -45,32 +45,45 @@ export default defineComponent({
showMenu.value = !showMenu.value;
};
- let ad = null;
+ const choseAd = (): Instance['ads'][number] | null => {
+ if (props.specify) {
+ return props.specify as Instance['ads'][number];
+ }
- if (props.specify) {
- ad = props.specify;
- } else {
let ads = instance.ads.filter(ad => props.prefer.includes(ad.place));
if (ads.length === 0) {
ads = instance.ads.filter(ad => ad.place === 'square');
}
- const high = ads.filter(ad => ad.priority === 'high');
- const middle = ads.filter(ad => ad.priority === 'middle');
- const low = ads.filter(ad => ad.priority === 'low');
+ const lowPriorityAds = ads.filter(ad => ad.ratio === 0);
+ ads = ads.filter(ad => ad.ratio !== 0);
- if (high.length > 0) {
- ad = high[Math.floor(Math.random() * high.length)];
- } else if (middle.length > 0) {
- ad = middle[Math.floor(Math.random() * middle.length)];
- } else if (low.length > 0) {
- ad = low[Math.floor(Math.random() * low.length)];
+ if (ads.length === 0) {
+ if (lowPriorityAds.length !== 0) {
+ return lowPriorityAds[Math.floor(Math.random() * lowPriorityAds.length)];
+ } else {
+ return null;
+ }
}
- }
+
+ const totalFactor = ads.reduce((a, b) => a + b.ratio, 0);
+ const r = Math.random() * totalFactor;
+
+ let stackedFactor = 0;
+ for (const ad of ads) {
+ if (r >= stackedFactor && r <= stackedFactor + ad.ratio) {
+ return ad;
+ } else {
+ stackedFactor += ad.ratio;
+ }
+ }
+
+ return null;
+ };
return {
- ad,
+ ad: choseAd(),
showMenu,
toggleMenu,
host,
diff --git a/src/client/instance.ts b/src/client/instance.ts
index bd6b1bd571..ad9e1a95fd 100644
--- a/src/client/instance.ts
+++ b/src/client/instance.ts
@@ -3,10 +3,16 @@ import { api } from './os';
// TODO: 他のタブと永続化されたstateを同期
-type Instance = {
+export type Instance = {
emojis: {
category: string;
}[];
+ ads: {
+ ratio: number;
+ place: string;
+ url: string;
+ imageUrl: string;
+ }[];
};
const data = localStorage.getItem('instance');
diff --git a/src/client/pages/instance/ads.vue b/src/client/pages/instance/ads.vue
index 20747d6f9c..6b536793b7 100644
--- a/src/client/pages/instance/ads.vue
+++ b/src/client/pages/instance/ads.vue
@@ -15,12 +15,17 @@
<MkRadio v-model="ad.place" value="horizontal">horizontal</MkRadio>
<MkRadio v-model="ad.place" value="horizontal-big">horizontal-big</MkRadio>
</div>
+ <!--
<div style="margin: 32px 0;">
{{ $ts.priority }}
<MkRadio v-model="ad.priority" value="high">{{ $ts.high }}</MkRadio>
<MkRadio v-model="ad.priority" value="middle">{{ $ts.middle }}</MkRadio>
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
</div>
+ -->
+ <MkInput v-model:value="ad.ratio" type="number">
+ <span>{{ $ts.ratio }}</span>
+ </MkInput>
<MkInput v-model:value="ad.expiresAt" type="date">
<span>{{ $ts.expiration }}</span>
</MkInput>
@@ -82,6 +87,7 @@ export default defineComponent({
memo: '',
place: 'square',
priority: 'middle',
+ ratio: 1,
url: '',
imageUrl: null,
expiresAt: null,
diff --git a/src/models/entities/ad.ts b/src/models/entities/ad.ts
index 3279de29ea..b2fc04c4f0 100644
--- a/src/models/entities/ad.ts
+++ b/src/models/entities/ad.ts
@@ -23,11 +23,17 @@ export class Ad {
})
public place: string;
+ // 今は使われていないが将来的に活用される可能性はある
@Column('varchar', {
length: 32, nullable: false
})
public priority: string;
+ @Column('integer', {
+ default: 1, nullable: false
+ })
+ public ratio: number;
+
@Column('varchar', {
length: 1024, nullable: false
})
diff --git a/src/server/api/endpoints/admin/ad/create.ts b/src/server/api/endpoints/admin/ad/create.ts
index 7777e95e6e..337114a3fa 100644
--- a/src/server/api/endpoints/admin/ad/create.ts
+++ b/src/server/api/endpoints/admin/ad/create.ts
@@ -22,6 +22,9 @@ export const meta = {
priority: {
validator: $.str
},
+ ratio: {
+ validator: $.num.int().min(0)
+ },
expiresAt: {
validator: $.num.int()
},
@@ -39,6 +42,7 @@ export default define(meta, async (ps) => {
url: ps.url,
imageUrl: ps.imageUrl,
priority: ps.priority,
+ ratio: ps.ratio,
place: ps.place,
memo: ps.memo,
});
diff --git a/src/server/api/endpoints/admin/ad/update.ts b/src/server/api/endpoints/admin/ad/update.ts
index 694af98394..71e6054a88 100644
--- a/src/server/api/endpoints/admin/ad/update.ts
+++ b/src/server/api/endpoints/admin/ad/update.ts
@@ -29,6 +29,9 @@ export const meta = {
priority: {
validator: $.str
},
+ ratio: {
+ validator: $.num.int().min(0)
+ },
expiresAt: {
validator: $.num.int()
},
@@ -52,6 +55,7 @@ export default define(meta, async (ps, me) => {
url: ps.url,
place: ps.place,
priority: ps.priority,
+ ratio: ps.ratio,
memo: ps.memo,
imageUrl: ps.imageUrl,
expiresAt: new Date(ps.expiresAt),
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 5b7292ef16..d170317f1c 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -511,7 +511,7 @@ export default define(meta, async (ps, me) => {
ads: ads.map(ad => ({
url: ad.url,
place: ad.place,
- priority: ad.priority,
+ ratio: ad.ratio,
imageUrl: ad.imageUrl,
})),
enableEmail: instance.enableEmail,