/*
* ShootOFF - Software for Laser Dry Fire Training
* Copyright (C) 2016 phrack
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.shootoff.plugins;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import com.shootoff.camera.Shot;
import com.shootoff.targets.Hit;
import com.shootoff.targets.Target;
import com.shootoff.targets.TargetRegion;
/**
* Merge of ParForScore and RandomShoot.
*
* @author Edward Kort
*
*/
public class ParRandomShot extends ParForScore {
private final List<String> subtargets = new ArrayList<>();
private final Random rng = new Random();
private boolean foundTarget;
private int currentSubtarget;
public ParRandomShot() {
}
public ParRandomShot(List<Target> targets) {
super(targets);
fetchSubtargets(targets);
}
@Override
public ExerciseMetadata getInfo() {
return new ExerciseMetadata("PAR Drill with a random Subtarget", "1.0", "Edward Kort",
"This exercise works with targets that have subtarget tags "
+ "assigned to some regions. When the exercise is started you "
+ "are asked to enter a range for randomly delayed starts, and "
+ "for the interval (PAR time) in which those scores will be "
+ "counted. You are then given 10 seconds to position yourself. "
+ "After a random wait (within the entered range), a randomly "
+ "selected subtarget is called out, telling you to draw the "
+ "pistol from its holster and fire at your target; a chime "
+ "signals the end of the Par time, to finally re-holster. The "
+ "score for each shot, performed during the PAR time and hitting "
+ "the subtarget, is points assigned to that subtarget (or 1 if "
+ "there is no assignment). This process is repeated as long as " + "this exercise is on.");
}
@Override
protected void initService() {
if (foundTarget) {
super.initService();
}
}
@Override
protected void doRound() {
pickSubtarget();
saySubtarget();
pauseShotDetection(false);
startRoundTimer();
try {
Thread.sleep((long) (parTime * 1000.));
} catch (final InterruptedException e) {
e.printStackTrace();
}
TrainingExerciseBase.playSound("sounds/chime.wav");
pauseShotDetection(true);
countScore = false;
}
@Override
public void shotListener(Shot shot, Optional<Hit> hit) {
setLength();
if (!foundTarget || !hit.isPresent() || !countScore) return;
final String subtarget = subtargets.get(currentSubtarget);
final String hitTarget = getSubtarget(Optional.of(hit.get().getHitRegion()));
if (subtarget.equals(hitTarget)) {
final String points = getPoints(Optional.of(hit.get().getHitRegion()));
setPoints(shot.getColor(), points);
}
}
@Override
protected void resetValues() {
super.resetValues();
final List<Target> targets = super.getCurrentTargets();
fetchSubtargets(targets);
}
private String getPoints(Optional<TargetRegion> hitRegion) {
String points = "1";
if (hitRegion.isPresent()) {
final TargetRegion region = hitRegion.get();
if (region.getAllTags().containsKey("points")) {
points = region.getTag("points");
}
}
return points;
}
private String getSubtarget(Optional<TargetRegion> hitRegion) {
String subtargetName = null;
if (hitRegion.isPresent()) {
final TargetRegion region = hitRegion.get();
if (region.getAllTags().containsKey("subtarget")) {
subtargetName = region.getTag("subtarget");
}
}
return subtargetName;
}
/**
* @see RandomShoot.fetchSubtargets
* @param targets
* @return
*/
private void fetchSubtargets(List<Target> targets) {
subtargets.clear();
foundTarget = false;
for (final Target target : targets) {
for (final TargetRegion region : target.getRegions()) {
if (region.getAllTags().containsKey("subtarget")) {
subtargets.add(region.getTag("subtarget"));
foundTarget = true;
}
}
if (foundTarget) break;
}
if (!foundTarget) {
playSound(new File("sounds/voice/shootoff-subtargets-warning.wav"));
}
}
private void pickSubtarget() {
if (foundTarget) {
currentSubtarget = rng.nextInt(subtargets.size());
}
}
private void saySubtarget() {
if (foundTarget) {
final String subValue = subtargets.get(currentSubtarget);
final File targetNameSound = new File(String.format("sounds/voice/shootoff-%s.wav", subValue));
if (targetNameSound.exists()) {
playSound(targetNameSound);
} else {
// We don't have a voice actor sounds file for a target
// subregion, fall back
// to TTS
TextToSpeech.say(subValue);
}
}
}
}