import { Component, AfterViewInit, QueryList, ViewChildren, OnInit } from '@angular/core';

import { VtSelectAnswerComponent } from './select-answer/vt-select-answer.component';
import { AnswerService } from './select-answer/answer.service';
import { Answer } from './select-answer/answer';

import { VtTranslationPairComponent } from './translation-pair/vt-translation-pair.component';
import { TranslationPairService } from './translation-pair/translation-pair.service';
import { TranslationPair } from './translation-pair/translation-pair';

import { VtCounterAnswerComponent } from './counter-answer/vt-counter-answer.component';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    providers: [
        AnswerService,
        TranslationPairService
    ]
})
export class AppComponent implements OnInit, AfterViewInit {
    availableTranslationPairs: TranslationPair[];
    availableAnswers: Answer[];
    totalSelectedAnswers: number = 0;
    correctSelectedAnswers: number = 0;
    @ViewChildren(VtSelectAnswerComponent) vtSelectList: QueryList<VtSelectAnswerComponent>;

    constructor(
        private answerService: AnswerService,
        private translationService: TranslationPairService
    ) {}

    ngOnInit() {
        this.availableAnswers = this.answerService.getAnswers();
        this.availableTranslationPairs = this.translationService.getTranslationPairs();
    }

    ngAfterViewInit() {}

    onAnswerChange(answer: Answer) {
        console.log('onAnswerChange: answer = ', answer);
        this.totalSelectedAnswers = 0;
        this.correctSelectedAnswers = 0;
        setTimeout(() => {
            this.vtSelectList.toArray().forEach((elem) => {
                console.log('onAnswerChange: elem = ', elem);
                if (elem.selectedAnswer.value) {
                    ++this.totalSelectedAnswers;
                }
                if (elem.selectedAnswer.correct) {
                    ++this.correctSelectedAnswers;
                }
            });
        }, 0);
    }

}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

import { VtSelectAnswerComponent } from './select-answer/vt-select-answer.component';
import { VtCounterAnswerComponent } from './counter-answer/vt-counter-answer.component';
import { VtTranslationPairComponent } from './translation-pair/vt-translation-pair.component';

@NgModule({
    declarations: [
        AppComponent,
        VtSelectAnswerComponent,
        VtCounterAnswerComponent,
        VtTranslationPairComponent
    ],
    imports: [
        BrowserModule,
        FormsModule
    ],
    providers: [],
    bootstrap: [
        AppComponent
    ]
})
export class AppModule {}
<h1>Exercise-1: Answer Select</h1>
<h2>Question #1:</h2>
<vt-select-answer [answers]="availableAnswers" (onAnswerChange)="onAnswerChange($event)"></vt-select-answer>
<h2>Question #2:</h2>
<vt-select-answer [answers]="availableAnswers" (onAnswerChange)="onAnswerChange($event)"></vt-select-answer>
<h2>Question #3:</h2>
<vt-select-answer [answers]="availableAnswers" (onAnswerChange)="onAnswerChange($event)"></vt-select-answer>


<vt-counter-answer [total]="totalSelectedAnswers" [correct]="correctSelectedAnswers"></vt-counter-answer>


<hr/>


<h1>Exercise-2: Translation Pair</h1>
<p><em>(Press "Spacebar" keyboard to show next translation pair)</em></p>
<vt-translation-pair [translationPairs]="availableTranslationPairs"></vt-translation-pair>


<hr/>
hr{
    margin: 2em 0;
}
import {Injectable} from "@angular/core";

import {ANSWERS} from "./mock-select-answers";

@Injectable()
export class AnswerService {
    getAnswers() {
        return ANSWERS;
    }
}
export class Answer {
    value: string;
    correct: boolean;
}
import { Answer } from './answer'

export var ANSWERS: Answer[] = [
    {value: 'apple', correct: false},
    {value: 'banana', correct: true},
    {value: 'perl', correct: false},
    {value: 'nuts', correct: true},
    {value: 'berry', correct: false},
    {value: 'coco', correct: true},
];
import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';

import { Answer } from './answer';

@Component({
    selector: 'vt-select-answer',
    templateUrl: './vt-select-answer.html',
    styleUrls: ['./vt-select-answer.css']
})
export class VtSelectAnswerComponent implements OnInit {
    @Input() answers;
    @Output() onAnswerChange:EventEmitter<any> = new EventEmitter<Answer>();

    selectedAnswer: Answer = {value:'', correct:false};
    emptyAnswer: Answer = {value:'', correct:false};
    selectData: Answer;

    onSelect(answer: Answer): void {
        this.onAnswerChange.emit(answer);
        this.selectedAnswer = answer;
    }

    ngOnInit(): void {
        this.selectData = this.emptyAnswer;
    }
}
form {
    width:50%;
    margin:0;
}
select {
    padding:0.5em;
}
<form>
    <select name="select" [(ngModel)]="selectData" (ngModelChange)="onSelect($event)">
        <option [ngValue]="emptyAnswer" [attr.selected]="true">-- select Answer --</option>
        <option *ngFor="let answer of answers" [ngValue]="answer">{{answer.value}}</option>
    </select>
</form>
import { TranslationPair } from './translation-pair'

export var TRANSLATIONS: TranslationPair[] = [
    {word: 'apple', translation: 'яблоко'},
    {word: 'banana', translation: 'банан'},
    {word: 'nuts', translation: 'орех'},
    {word: 'melon', translation: 'дыня'},
    {word: 'berry', translation: 'ягода'},
];
import {Injectable} from "@angular/core";

import {TRANSLATIONS} from "./mock-translation-pairs";

@Injectable()
export class TranslationPairService {
    getTranslationPairs() {return TRANSLATIONS;}
}
export class TranslationPair {
    word: string;
    translation: string;
}
import { Component, EventEmitter, Input, Output, OnInit, HostListener} from '@angular/core';

import { TranslationPair } from './translation-pair';

@Component({
    selector: 'vt-translation-pair',
    templateUrl: './vt-translation-pair.html',
    styleUrls: ['./vt-translation-pair.css']
})
export class VtTranslationPairComponent implements OnInit {
    @Input() translationPairs: TranslationPair[] = [];
    currentPair: TranslationPair = {word:'', translation:''};

    @HostListener("window:keydown", ["$event"])
    onKeyDown($event:any) {
        if ($event.keyCode == 32) {
            this.randomTranslationPair();
        };
    }

    ngOnInit(): void {
        this.randomTranslationPair();
    }

    getRandomInt(min: number, max: number): number {
        return Math.floor( Math.random() * (max - min + 1) ) + min;
    }

    randomTranslationPair(): void {
        var totalPairs, randomIndex;
        totalPairs = this.translationPairs.length;
        if (totalPairs) {
            randomIndex = this.getRandomInt(0, totalPairs - 1);
            this.currentPair = this.translationPairs[randomIndex];
        }
    }
}
.trans-pair-wrapper{
    font-size: 2em;
    color:dimgray;
}
<div class="trans-pair-wrapper">
    <p><strong>Word:</strong> {{currentPair.word}}</p>
    <p><strong>Translation</strong>: {{currentPair.translation}}</p>
</div>
import { Component, Input } from '@angular/core';

@Component({
    selector: 'vt-counter-answer',
    templateUrl: './vt-counter-answer.html',
    styleUrls: ['./vt-counter-answer.css']
})
export class VtCounterAnswerComponent {
    @Input() total:number = 0;
    @Input() correct:number = 0;
}
.counter-wrapper{
    box-sizing: border-box;
    background: #333;
    color: #efefef;
    padding: 0.5em 1em;
    margin: 1em 0px;
    width: 50%;
}
<div class="counter-wrapper">
    <p><strong>Total Answers:</strong> {{total}}</p>
    <p><strong>Correct Answers:</strong> {{correct}}</p>
</div>
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);


/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://v2.angular.io/license
*/
<!DOCTYPE html>
<html>

<head>
  <title>Angular Quickstart</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body {
      color: #369;
      font-family: Arial, Helvetica, sans-serif;
    }
  </style>

  <!-- Polyfills -->
  <script src="https://unpkg.com/core-js/client/shim.min.js"></script>

  <script src="https://unpkg.com/zone.js@0.7.4?main=browser"></script>
  <script src="https://unpkg.com/systemjs@0.19.39/dist/system.src.js"></script>
  <script src="systemjs.config.js"></script>
  <script>
    System.import('main.js').catch(function(err) {
      console.error(err);
    });
  </script>
</head>

<body>
  <app-root>Loading AppComponent content here ...</app-root>
</body>

</html>


<!-- 
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://v2.angular.io/license
-->
/**
 * WEB ANGULAR VERSION
 * (based on systemjs.config.js in angular.io)
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      // Copy of compiler options in standard tsconfig.json
      "target": "es5",
      "module": "commonjs",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "lib": ["es2015", "dom"],
      "noImplicitAny": true,
      "suppressImplicitAnyIndexErrors": true
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: {
      // paths serve as alias
      'npm:': 'https://unpkg.com/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      'app': 'app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
      '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',

      // other libraries
      'rxjs':                      'npm:rxjs@5.0.1',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
      'ts':                        'npm:plugin-typescript@5.2.7/lib/plugin.js',
      'typescript':                'npm:typescript@2.0.10/lib/typescript.js',

    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.ts',
        defaultExtension: 'ts',
        meta: {
          './*.ts': {
            loader: 'systemjs-angular-loader.js'
          }
        }
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });

})(this);

/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://v2.angular.io/license
*/
var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm;
var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g;
var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g;

module.exports.translate = function(load){
  var url = document.createElement('a');
  url.href = load.address;

  var basePathParts = url.pathname.split('/');

  basePathParts.pop();
  var basePath = basePathParts.join('/');

  var baseHref = document.createElement('a');
  baseHref.href = this.baseURL;
  baseHref = baseHref.pathname;

  basePath = basePath.replace(baseHref, '');

  load.source = load.source
    .replace(templateUrlRegex, function(match, quote, url){
      let resolvedUrl = url;

      if (url.startsWith('.')) {
        resolvedUrl = basePath + url.substr(1);
      }

      return 'templateUrl: "' + resolvedUrl + '"';
    })
    .replace(stylesRegex, function(match, relativeUrls) {
      var urls = [];

      while ((match = stringRegex.exec(relativeUrls)) !== null) {
        if (match[2].startsWith('.')) {
          urls.push('"' + basePath + match[2].substr(1) + '"');
        } else {
          urls.push('"' + match[2] + '"');
        }
      }

      return "styleUrls: [" + urls.join(', ') + "]";
    });

  return load;
};
# Answer App Angular
1. Write an application where two components would work:
  * The first - select exercise. At the input, the component receives an array of responses (the string + the correct flag).
    * Example: [{value: "apple", correct: false}, {value: "pear", correct: true}, {value: "pineapple", correct: false}]
    * Exercise looks like a normal html select, offering to select the answer from the list.
  * The second - counter for displaying the number of points.
    * Displays only 2 numbers:
    * the total number of selected answers on the page;
    * the number of exercises where the correct answer is selected.

2. Write a component that implements the widget to learn words.
  * At the input, the component takes an array of words and translations.
  * Example: [{word: "apple", translation: "apple"}, {word: "nuts", translation: "орех"}]
  * The component should display only one pair of words at a time, switching to the next pair occurs when the spacebar is pressed.