source: orbit/iOS/Orbit/Orbit/controllers/FlightViewController.m @ af91708

Servo
Last change on this file since af91708 was af91708, checked in by Steve Castellotti <sc@…>, 8 years ago
  • displayScore() added
  • resetCurrentScore() added
  • Last score processing working
  • Property mode set to 100644
File size: 9.9 KB
RevLine 
[ab9d63b]1//
2//  FlightViewController.m
3//  Orbit
4//
5//  Copyright (c) 2013 Puzzlebox Productions, LLC. All rights reserved.
6//  Originally created by Jonathon Horsman.
7//
8//  This code is released under the GNU Public License (GPL) version 2
9//  For more information please refer to http://www.gnu.org/copyleft/gpl.html
10//
11
12#import <QuartzCore/QuartzCore.h>
13#import "FlightViewController.h"
14#import "AppDelegate.h"
15#import "SignalConverter.h"
16
17#define STATUS_DEFAULT 0
18#define STATUS_CONNECTING 1
19#define STATUS_CONNECTED 2
20#define STATUS_PROCESSING 3
21#define STATUS_ACTIVE 4
22
23@implementation FlightViewController {
[ad80ed2]24   SignalConverter *signalConverter;
25   int deviceStatus;
26   BOOL warned;
[ab9d63b]27}
28
[8a0f920f]29@synthesize attention, meditation, signal, power, attentionThreshold, meditationThreshold, connectButton, testButton, statusImage, signalPercent, attentionPercent, meditationPercent, powerPercent;
[ab9d63b]30
31- (void)viewDidLoad
32{
[ad80ed2]33   [super viewDidLoad];
34   
35   attention.progressTintColor = [UIColor redColor];
36   self.attentionThreshold.minimumTrackTintColor = [UIColor grayColor];
37   meditation.progressTintColor = [UIColor blueColor];
38   self.meditationThreshold.minimumTrackTintColor = [UIColor grayColor];
39   self.meditationThreshold.value = 0;
[ba2b6ff]40   
[ad80ed2]41   AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
42   signalConverter = appDelegate.signalConverter;
43   
44   signalConverter.delegate = self;
45   [self setThresholds];
46   [self.attentionThreshold addTarget:self action:@selector(setThresholds) forControlEvents:UIControlEventValueChanged];
47   [self.meditationThreshold addTarget:self action:@selector(setThresholds) forControlEvents:UIControlEventValueChanged];
[ad40faa]48   
[ab9d63b]49}
50
51#pragma mark view updates
52
53// Set all levels back to zero
54- (void) resetViews
55{
[ad80ed2]56   signal.progress = 0;
57   signalPercent.text = @"0%";
58   attention.progress = 0;
59   attentionPercent.text = @"0%";
60   meditation.progress = 0;
61   meditationPercent.text = @"0%";
62   power.progress = 0;
63   powerPercent.text = @"0%";
64   [self updateStatusImage:STATUS_DEFAULT];
65   connectButton.title = @"Connect";
[ab9d63b]66}
67
68- (void) updateStatusImage:(int) statusNo
69{
[ad80ed2]70   if (statusNo != deviceStatus) {
71      [statusImage setImage: [UIImage imageNamed:[NSString stringWithFormat:@"status_%u", statusNo]]];
72      deviceStatus = statusNo;
73   }
[ab9d63b]74}
75
[8a0f920f]76- (void) setThresholds
[ab9d63b]77{
[ad80ed2]78   [signalConverter setValuesForAttention:attentionThreshold.value meditation:meditationThreshold.value];
[ab9d63b]79}
80
81#pragma mark - SignalConverterDelegate methods
82
83- (void) updatedValuesForSignal: (float)signalStrength
84                      attention: (float)attentionLevel
85                     meditation: (float)meditationLevel
86                          power: (float)powerLevel
87{
[af91708]88   
[ad80ed2]89   // Set Attention and Meditation to zero if we've lost signal
90   if (signalStrength < 100.0) {
91      attentionLevel = 0.000000;
92      meditationLevel = 0.000000;
93      powerLevel = 0.000000;
94   }
[d249b65]95   
[ad80ed2]96   self.signal.progress = signalStrength / 100;
97   self.signalPercent.text = [NSString stringWithFormat:@"%i%%", (int)(signalStrength)];
98   self.attention.progress = attentionLevel;
99   self.attentionPercent.text = [NSString stringWithFormat:@"%i%%", (int)(attentionLevel * 100)];
100   self.meditation.progress = meditationLevel;
101   self.meditationPercent.text = [NSString stringWithFormat:@"%i%%", (int)(meditationLevel * 100)];
102   self.power.progress = powerLevel;
103   self.powerPercent.text = [NSString stringWithFormat:@"%i%%", (int)(powerLevel * 100)];
104   [self updateStatusImage:[self statusFromSignal:signalStrength power:powerLevel]];
[d249b65]105   
[b5aa714]106   [self updateScores];
107   
[9015b1e]108}
109
110- (int) statusFromSignal: (float)signalLevel power:(float)powerLevel
111{
[812f274]112   
[af91708]113   //   NSLog(@"signalLevel: %f | powerLevel: %f", signalLevel, powerLevel);
[812f274]114   
115   if (signalLevel == 0.0) { // no signal
116      return STATUS_CONNECTING;
117   }
118   
119   if (signalLevel < 100.0) { // poor signal
[ad80ed2]120      return STATUS_CONNECTED;
[812f274]121   }
122   
123   if (powerLevel == 0.0) { // strong signal but thresholds not met
[ad80ed2]124      return STATUS_PROCESSING;
125   } else { // flight command sent to orbit
126      return STATUS_ACTIVE;
127   }
[812f274]128   
[ab9d63b]129}
130
131- (void) notifyHeadsetConnect
132{
[ad80ed2]133   [self updateStatusImage:STATUS_CONNECTING];
[ab9d63b]134}
135
136- (void) notifyHeadsetDisconnect
137{
[ad80ed2]138   // Reset the outputs back to zero
139   [self resetViews];
[ab9d63b]140}
141
142- (void) notifyDeviceConnected:(NSString *)name
143{
[ad80ed2]144   [self updateStatusImage:STATUS_CONNECTING];
145   connectButton.title = @"Disconnect";
[9015b1e]146}
147
148- (void) appStopped
149{
[ad80ed2]150   [self resetViews]; // just in case it didn't happen on close
[ab9d63b]151}
152
153#pragma mark - button press events
154
155- (IBAction) connectButtonPressed:(id) sender {
[ad80ed2]156   
157   if (signalConverter.running) {
158      [signalConverter stopProcessing];
159      [self resetViews];
160   } else {
161      BOOL volumeMax  = [signalConverter isVolumeMax];
162      BOOL headphones = [signalConverter isAudioJackPlugged];
163     
164      if (!warned && !volumeMax && !headphones) {
165         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Check Volume & Transmitter" message:@"Ensure the volume is at max and the transmitter is plugged into the headphones" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
166         [alert show];
167      } else if (!warned && !volumeMax) {
168         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Turn Up The Volume" message:@"Your device volume must be at the maximum for proper operation" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
169         [alert show];
170      } else if (!warned && !headphones) {
171         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Plug In The Transmitter" message:@"Ensure the infrared transmitter is plugged into the headphone jack" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
172         [alert show];
173      } else if (!signalConverter.isBluetoothReady) {
174         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Device not found" message:@"No Bluetooth device detected. Ensure Bluetooth is on and the Mindwave headset is paired" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
175         [alert show];
176      } else if ([signalConverter startProcessing]) {
177         connectButton.title = @"Disconnect";
178      } else {
179         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to connect" message:@"Check the device is correctly paired on Bluetooth" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
180         [alert show];
181      }
182      warned = YES;
183   }
[ab9d63b]184}
185
[de10cbc]186- (IBAction) testButtonPressed:(id) sender {
[4a56cfb]187   
[af91708]188   //   NSLog(@"Available fonts: %@", [UIFont familyNames]);
[4a56cfb]189   
[ad80ed2]190   [signalConverter isAudioJackPlugged];
191   if (signalConverter.running) {
[3434fbc]192      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Signal Processing Active" message:@"Please press the Disconnect button before sending a Test signal" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[ad80ed2]193      [alert show];
194   } else {
195      if (signalConverter.testing) {
196         testButton.title = @"Test";
197         [signalConverter stopTestSound];
198      } else {
199         testButton.title = @"Stop";
200         [signalConverter playTestSound];
201      }
202   }
[de10cbc]203}
204
[b5aa714]205- (void) updateScores
206{
[af91708]207   
[b5aa714]208   //   /**
209   //    * Score points based on target slider levels
210   //    * If you pass your goal with either Attention or Meditation
211   //    * the higher target of the two will counts as points per second.
212   //    *
213   //    * Minimum threshold for points is set as "minimumScoreTarget"
214   //    *
215   //    * For example, assume minimumScoreTarget is 40%.
216   //    * If your target Attention is 60% and you go past to reach 80%
217   //    * you will receive 20 points per second (60-40). If your
218   //    * target is 80% and you reach 80% you will receive 40
219   //    * points per second (80-40).
220   //    *
221   //    * You can set both Attention and Meditation targets at the
222   //    * same time. Reaching either will fly the helicopter but you
223   //    * will only receive points for the higher-scoring target of
224   //    * the two.
225   //    *
226   //    */
227   
228   int eegAttentionScore = 0;
229   int eegAttention = self.attention.progress * 100;
230   int eegAttentionTarget = self.attentionThreshold.value * 100;
[af91708]231   
[b5aa714]232   int eegMeditationScore = 0;
233   int eegMeditation = self.meditation.progress * 100;
234   int eegMeditationTarget = self.meditationThreshold.value * 100;
235   
[af91708]236   
[b5aa714]237   if ((eegAttention >= eegAttentionTarget) &&
238       (eegAttentionTarget > minimumScoreTarget))
239      eegAttentionScore = eegAttentionTarget - minimumScoreTarget;
240   
241   if ((eegMeditation >= eegMeditationTarget) &&
242       (eegMeditationTarget > minimumScoreTarget))
243      eegMeditationScore = eegMeditationTarget - minimumScoreTarget;
244   
245   if (eegAttentionScore > eegMeditationScore)
246      scoreCurrent = scoreCurrent + eegAttentionScore;
247   else
248      scoreCurrent = scoreCurrent + eegMeditationScore;
249   
250   
[af91708]251   // High score
252   if (scoreCurrent > scoreHigh) {
253      scoreHigh = scoreCurrent;
254   }
[b5aa714]255   
[af91708]256   // Reset score
257   if (power.progress == 0)
258      [self resetCurrentScore];
[b5aa714]259   
[af91708]260   
261   // Catch anyone gaming the system with one slider
262   // below the minimum threshold and the other over.
263   // For example, setting Meditation to 1% will keep helicopter
264   // activated even if Attention is below target
265   if ((eegAttention < eegAttentionTarget) && (eegMeditation < minimumScoreTarget))
266      [self resetCurrentScore];
267   
268   if ((eegMeditation < eegMeditationTarget) && (eegAttention < minimumScoreTarget))
269      [self resetCurrentScore];
270   
271   if ((eegAttention < minimumScoreTarget) && (eegMeditation < minimumScoreTarget))
272      [self resetCurrentScore];
273   
274   
275   [self displayScore];
276   
277   
278} // updateScore
[b5aa714]279
280
[af91708]281// ################################################################
[b5aa714]282
[af91708]283- (void) displayScore
284{
285   self.scoresDisplay.text = [NSString stringWithFormat:@"Scores        Current: %i    Last: %i    High: %i", (int)scoreCurrent, (int)scoreLast, (int)scoreHigh];
286}
[b5aa714]287
288// ################################################################
289
[af91708]290- (void) resetCurrentScore
291{
292   if (scoreCurrent > 0)
293      scoreLast = scoreCurrent;
294   
295   scoreCurrent = 0;
296   
297} // resetCurrentScore
[b5aa714]298
[ab9d63b]299@end
Note: See TracBrowser for help on using the repository browser.