diff --git a/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.css b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.css
new file mode 100644
index 0000000..b1588ae
--- /dev/null
+++ b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.css
@@ -0,0 +1,207 @@
+.control {
+ z-index: 1500;
+}
+
+.gacha-button-group {
+ width: 100%;
+ display: flex;
+}
+
+.gacha-button-group button {
+ margin: auto;
+ width: 128px;
+ height: 128px;
+ background-color: dimgray;
+}
+
+.full-screen {
+ z-index: 1000;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+ background: url("//static.samnyan.icu/ongeki/gameUi/Evt_BattleStart_UI_CMN_Transition_bg.png") no-repeat center;
+ background-size: cover;
+}
+
+/* Wide screen */
+.card-container {
+ padding: 0 5%;
+ height: 100%;
+ margin: 0;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ overflow: scroll;
+ -ms-overflow-style: none;
+}
+
+.card-container::-webkit-scrollbar {
+ display: none;
+}
+
+.result-card {
+ margin: 30px 20px;
+ width: 30%;
+ height: fit-content;
+ max-width: 200px;
+ overflow: hidden;
+ position: relative;
+}
+
+.result-card .overlay {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+}
+
+.result-card .overlay img {
+ left: 0;
+ position: absolute;
+ height: 100%;
+ transform: scaleX(-1);
+ opacity: 60%;
+ animation-duration: 3s;
+ animation-name: overlay-glow;
+ animation-iteration-count: infinite;
+ animation-direction: normal;
+}
+
+.result-card .overlay-rarity {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+}
+
+.result-card .overlay-rarity img {
+ left: 0;
+ position: absolute;
+ height: 100%;
+ opacity: 0;
+ animation-duration: 2.5s;
+ animation-name: overlay-rarity;
+ animation-iteration-count: infinite;
+ animation-direction: alternate;
+}
+
+@keyframes overlay-glow {
+ from {
+ left: -1000%;
+ }
+
+ to {
+ left: 300%;
+ }
+}
+
+@keyframes overlay-rarity {
+ 20% {
+ opacity: 0;
+ }
+
+ 50% {
+ opacity: 60%;
+ }
+
+ 80% {
+ opacity: 0;
+ }
+}
+
+.flip {
+ transform: rotateY(180deg);
+}
+
+.card-image {
+ transition: transform 0.8s;
+ transform-style: preserve-3d;
+}
+
+.card-image .image-back {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+ transform: rotateY(180deg);
+}
+
+.card-image .image-back img {
+ left: 0;
+ position: absolute;
+ height: 100%;
+}
+
+.image-front, .image-back {
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+
+.image-front img, .image-back img {
+ width: 100%;
+}
+
+@media screen and (max-width: 600px) {
+ .result-card {
+ margin: 30px 15px;
+ max-width: 150px;
+ }
+
+ .gacha-button-group button {
+ width: 72px;
+ height: 72px;
+ }
+}
+
+@media screen and (max-height: 500px) {
+ .result-card {
+ max-width: 110px;
+ }
+}
+
+@media screen and (max-width: 420px) {
+ .result-card {
+ margin: 30px 5px;
+ max-width: 100px;
+ }
+}
+
+
+/**
+Card animation part
+ */
+
+.card-animation-full-screen {
+ z-index: 1200;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+ display: none;
+}
+
+#card_animation {
+ margin: auto;
+ max-height: 100%;
+ max-width: 100%;
+}
+
+#image_loader {
+ display: none;
+}
diff --git a/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.html b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.html
new file mode 100644
index 0000000..c57b618
--- /dev/null
+++ b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.html
@@ -0,0 +1,55 @@
+
+
+ Regular Gacha
+ This is still work in progress. Animation isn't implemented.
+
+
+
+
+
+ Detail:
+ R: 70%
+ SR: 25%
+ SSR: 5%
+
+ 0">
+ Card data saved in server: {{submitSuccessful}} , failed {{cardResultList.length - submitSuccessful}}
+
+
+
+
+
+
+
+
+
+

+
+
+

+
+
+
+

+
+
+

+
+
+

+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.spec.ts b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.spec.ts
new file mode 100644
index 0000000..6902713
--- /dev/null
+++ b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.spec.ts
@@ -0,0 +1,25 @@
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {OngekiCardGachaComponent} from './ongeki-card-gacha.component';
+
+describe('OngekiCardGachaComponent', () => {
+ let component: OngekiCardGachaComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [OngekiCardGachaComponent]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OngekiCardGachaComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.ts b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.ts
new file mode 100644
index 0000000..1ff7c59
--- /dev/null
+++ b/src/app/sega/ongeki/ongeki-card-gacha/ongeki-card-gacha.component.ts
@@ -0,0 +1,151 @@
+import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
+import {environment} from '../../../../environments/environment';
+import {OngekiCard} from '../model/OngekiCard';
+import {ApiService} from '../../../api.service';
+import {AuthenticationService} from '../../../auth/authentication.service';
+import {MessageService} from '../../../message.service';
+import {NgxIndexedDBService} from 'ngx-indexed-db';
+import {animate, style, transition, trigger} from '@angular/animations';
+
+@Component({
+ selector: 'app-ongeki-card-gacha',
+ templateUrl: './ongeki-card-gacha.component.html',
+ styleUrls: ['./ongeki-card-gacha.component.css'],
+ animations: [
+ trigger('control', [
+ transition(':enter', [
+ style({opacity: 0}),
+ animate('1s 0.5s ease-out',
+ style({opacity: 1}))
+ ]),
+ transition(':leave', [
+ style({opacity: 1}),
+ animate('1s ease-in',
+ style({opacity: 0}))
+ ])
+ ])
+ ]
+})
+export class OngekiCardGachaComponent implements OnInit, AfterViewInit {
+
+ @ViewChild('card_animation', {static: true})
+ canvas: ElementRef;
+
+ host = environment.assetsHost;
+ assets = environment.assetsHost + 'ongeki/gameUi/';
+
+ isStarted = false;
+
+ rarity: number[] = [];
+ rList: OngekiCard[] = [];
+ srList: OngekiCard[] = [];
+ ssrList: OngekiCard[] = [];
+
+ cardResultList: CardResult[] = [];
+ currentShowedIndex = 0;
+
+ submitSuccessful = 0;
+
+ constructor(
+ private api: ApiService,
+ private auth: AuthenticationService,
+ private messageService: MessageService,
+ private dbService: NgxIndexedDBService
+ ) {
+ }
+
+ ngOnInit() {
+ this.rarity = Array(70).fill(1);
+ this.rarity = this.rarity.concat(Array(25).fill(2));
+ this.rarity = this.rarity.concat(Array(5).fill(3));
+ this.dbService.getAll('ongekiCard').then(
+ x => {
+ x.forEach(y => {
+ switch (y.rarity) {
+ case 'R':
+ this.rList.push(y);
+ break;
+ case 'SR':
+ this.srList.push(y);
+ break;
+ case 'SSR':
+ this.ssrList.push(y);
+ break;
+ }
+ });
+ }
+ );
+
+ }
+
+ ngAfterViewInit() {
+ // const ctx = this.canvas.nativeElement.getContext('2d');
+ //
+ // const img = new Image();
+ // img.onload = () => ctx.drawImage(img, 0, 0);
+ // img.src = this.assets + 'UI_CMN_CardGet_NEW.png';
+ }
+
+ start(count: number) {
+ this.cardResultList = [];
+ this.currentShowedIndex = 0;
+ this.isStarted = true;
+ this.submitSuccessful = 0;
+
+ for (let i = 0; i < count; i++) {
+ const rarity = this.rarity[Math.floor(Math.random() * 99)];
+ console.log('rarity: ' + rarity);
+ let card;
+ switch (rarity) {
+ case 1:
+ card = this.rList[Math.floor(Math.random() * this.rList.length)];
+ break;
+ case 2:
+ card = this.srList[Math.floor(Math.random() * this.srList.length)];
+ break;
+ case 3:
+ card = this.ssrList[Math.floor(Math.random() * this.ssrList.length)];
+ break;
+ }
+ console.log('card: ' + JSON.stringify(card));
+ this.cardResultList.push({
+ show: false,
+ card
+ });
+ }
+ this.submitCardData();
+ return;
+ }
+
+ open() {
+ console.log('clicked');
+ if (this.currentShowedIndex < this.cardResultList.length) {
+ const card = this.cardResultList[this.currentShowedIndex];
+ card.show = true;
+ this.currentShowedIndex = this.currentShowedIndex + 1;
+ } else {
+ this.isStarted = false;
+ }
+ }
+
+ submitCardData() {
+ const aimeId = this.auth.currentUserValue.extId;
+ this.cardResultList.forEach(x => {
+ this.api.post('api/game/ongeki/card', {
+ aimeId,
+ cardId: x.card.id
+ }).subscribe(
+ data => {
+ this.submitSuccessful = this.submitSuccessful + 1;
+ return;
+ },
+ error => this.messageService.notice(error)
+ );
+ });
+ }
+}
+
+interface CardResult {
+ show: boolean;
+ card: OngekiCard;
+}
diff --git a/src/app/sega/ongeki/ongeki-card/ongeki-card.component.html b/src/app/sega/ongeki/ongeki-card/ongeki-card.component.html
index 57dd0a2..29daab4 100644
--- a/src/app/sega/ongeki/ongeki-card/ongeki-card.component.html
+++ b/src/app/sega/ongeki/ongeki-card/ongeki-card.component.html
@@ -11,7 +11,7 @@
-
+
diff --git a/src/app/sega/ongeki/ongeki.module.ts b/src/app/sega/ongeki/ongeki.module.ts
index e49c69b..c83c8f9 100644
--- a/src/app/sega/ongeki/ongeki.module.ts
+++ b/src/app/sega/ongeki/ongeki.module.ts
@@ -17,6 +17,7 @@ import {OngekiRatingComponent} from './ongeki-rating/ongeki-rating.component';
import {ToLevelDecimalPipe} from './util/to-level-decimal.pipe';
import {ToBattleSpritePipe} from './util/to-battle-sprite.pipe';
import {ToTechSpritePipe} from './util/to-tech-sprite.pipe';
+import {OngekiCardGachaComponent} from './ongeki-card-gacha/ongeki-card-gacha.component';
@NgModule({
@@ -31,7 +32,8 @@ import {ToTechSpritePipe} from './util/to-tech-sprite.pipe';
OngekiRatingComponent,
ToLevelDecimalPipe,
ToBattleSpritePipe,
- ToTechSpritePipe
+ ToTechSpritePipe,
+ OngekiCardGachaComponent
],
imports: [
CommonModule,
diff --git a/src/app/sega/ongeki/ongeki.routing.ts b/src/app/sega/ongeki/ongeki.routing.ts
index 3c56db0..0a2687d 100644
--- a/src/app/sega/ongeki/ongeki.routing.ts
+++ b/src/app/sega/ongeki/ongeki.routing.ts
@@ -6,6 +6,7 @@ import {OngekiRecentComponent} from './ongeki-recent/ongeki-recent.component';
import {OngekiSongListComponent} from './ongeki-song-list/ongeki-song-list.component';
import {OngekiBattlePointComponent} from './ongeki-battle-point/ongeki-battle-point.component';
import {OngekiRatingComponent} from './ongeki-rating/ongeki-rating.component';
+import {OngekiCardGachaComponent} from './ongeki-card-gacha/ongeki-card-gacha.component';
const routes: Routes = [
@@ -16,6 +17,7 @@ const routes: Routes = [
{path: 'rating', component: OngekiRatingComponent},
{path: 'card', component: OngekiCardComponent},
{path: 'card/all', component: OngekiCardListComponent},
+ {path: 'card/gacha', component: OngekiCardGachaComponent},
];
export const OngekiRoutes = RouterModule.forChild(routes);