Created
November 15, 2011 02:11
-
-
Save Nub/1365914 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // main.m | |
| // fccRadioListParser | |
| // | |
| // Created by Zachry Thayer on 11/14/11. | |
| // Copyright (c) 2011 Zachry Thayer. All rights reserved. | |
| // | |
| #import <Foundation/Foundation.h> | |
| #import "JSONKit.h" | |
| #define kFCCStationsFile @"FCCStations.txt" | |
| #define kCountryCodesToNamesFile @"countryCodesToNames.json" | |
| #define kStateCodesToNamesFile @"stateCodesToNames.json" | |
| enum FCCIndexes{ | |
| Callsign = 1, | |
| Frequency, | |
| Service, | |
| Channel, | |
| DirectionalAntennaDAorNonDirectionalND, | |
| NotUsedforFM, | |
| FMStationClass, | |
| NotUsedforFM2, | |
| FMStatus, | |
| City, | |
| State, | |
| Country, | |
| FileNumberApplicationConstructionPermitorLicenseorDocketNumberRulemaking, | |
| EffectiveRadiatedPower__horizontallypolarizedmaximum, | |
| EffectiveRadiatedPower__verticallypolarizedmaximum, | |
| AntennaHeightAboveAverageTerrainHAAT__horizontalpolarization, | |
| AntennaHeightAboveAverageTerrainHAAT__verticalpolarization, | |
| FacilityIDNumberuniquetoeachstation, | |
| NorthOrSouthLatitude, | |
| DegreesLatitude, | |
| MinutesLatitude, | |
| SecondsLatitude, | |
| WestOrEastLongitude, | |
| DegreesLongitude, | |
| MinutesLongitude, | |
| SecondsLongitude, | |
| LicenseeorPermittee, | |
| Kilometersdistantradiusfromenteredlatitude,longitude, | |
| MilesDistantRadius, | |
| Azimuth, | |
| AntennaRadiationCenterAboveMeanSeaLevelRCAMSL_HorizontallyPolarized_meters, | |
| AntennaRadiationCenterAboveMeanSeaLevelRCAMSL_VerticallyPolarized_meters, | |
| DirectionalAntennaIDNumber, | |
| DirectionalAntennaPatternRotation, | |
| AntennaStructureRegistrationNumber, | |
| ApplicationID, | |
| FCCComponentsCount | |
| }; | |
| double decimalDegrees(double degrees, double minutes, double seconds); | |
| double decimalDegrees(double degrees, double minutes, double seconds){ | |
| return degrees + minutes/60.f + seconds/3600.f; | |
| } | |
| NSDictionary *countryCodesToNames = nil; | |
| NSDictionary *stateCodesToNames = nil; | |
| NSString *getCountryNameFromCode(NSString* countryCode); | |
| NSString *getCountryNameFromCode(NSString* countryCode){ | |
| // if first lookup load DB | |
| if (!countryCodesToNames) { | |
| NSData *countryCodesToNamesData = [NSData dataWithContentsOfFile:kCountryCodesToNamesFile]; | |
| countryCodesToNames = [countryCodesToNamesData objectFromJSONData]; | |
| } | |
| return [countryCodesToNames objectForKey:countryCode]; | |
| } | |
| NSString *getStateNameFromCode(NSString* stateCode, NSString *country); | |
| NSString *getStateNameFromCode(NSString* stateCode, NSString *country){ | |
| // if first lookup load DB | |
| if (!stateCodesToNames) { | |
| NSData *stateCodesToNamesData = [NSData dataWithContentsOfFile:kStateCodesToNamesFile]; | |
| stateCodesToNames = [stateCodesToNamesData objectFromJSONData]; | |
| } | |
| NSDictionary *thisCountry = [stateCodesToNames objectForKey:country];//Must know what country to look in. | |
| if (!thisCountry) { | |
| return nil; | |
| } | |
| return [thisCountry objectForKey:stateCode]; | |
| } | |
| void cleanup(); | |
| void cleanup(){ | |
| if (countryCodesToNames) { | |
| countryCodesToNames = nil;//let arc cleanup | |
| } | |
| } | |
| int main (int argc, const char * argv[]) | |
| { | |
| @autoreleasepool { | |
| NSString *fccStationsText = [NSString stringWithContentsOfFile:kFCCStationsFile encoding:NSUTF8StringEncoding error:nil]; | |
| if (!fccStationsText) { | |
| return -1;//Fail | |
| } | |
| NSMutableDictionary *fccStations = [NSMutableDictionary dictionary]; | |
| [fccStationsText enumerateLinesUsingBlock:^(NSString *line, BOOL *stop){ | |
| NSString *trimmedLine = [line stringByReplacingOccurrencesOfString:@" " withString:@""]; | |
| NSArray *lineComponents = [trimmedLine componentsSeparatedByString:@"|"]; | |
| if (!lineComponents ){//&& [lineComponents count] == FCCComponentsCount) { | |
| return;//Skip to next line, this one is invalid | |
| } | |
| NSString *thisCountryCode = [lineComponents objectAtIndex:Country]; | |
| NSString *thisCountryName = getCountryNameFromCode(thisCountryCode); | |
| if (!thisCountryName) { | |
| return;//Skip this country, it's not available. | |
| } | |
| NSString *thisStateCode = [lineComponents objectAtIndex:State]; | |
| NSString *thisStateName = getStateNameFromCode(thisStateCode, thisCountryName); | |
| if (!thisStateName) { | |
| return;//Skip this state, it's not available. | |
| } | |
| NSMutableDictionary *thisCountry = [fccStations objectForKey:thisCountryName]; | |
| if (!thisCountry) { | |
| //Setup Country if it doesn't exist | |
| thisCountry = [NSMutableDictionary dictionary]; | |
| [thisCountry setObject:thisCountryCode forKey:@"Code"]; | |
| [thisCountry setObject:[NSMutableDictionary dictionary] forKey:@"Regions"]; | |
| [fccStations setObject:thisCountry forKey:thisStateName]; | |
| } | |
| NSMutableDictionary *thisState = [[thisCountry objectForKey:@"Regions"] objectForKey:thisStateName]; | |
| if (!thisState) { | |
| thisState = [NSMutableDictionary dictionary]; | |
| [thisState setObject:thisStateCode forKey:@"Code"]; | |
| [thisState setObject:[NSMutableDictionary dictionary] forKey:@"RadioStations"]; | |
| [[thisCountry objectForKey:@"Regions"] setObject:thisState forKey:thisStateName]; | |
| } | |
| NSMutableDictionary *thisRadioStations = [thisState objectForKey:@"RadioStations"]; | |
| //Build station | |
| NSMutableDictionary *thisStation = [NSMutableDictionary dictionary]; | |
| if (!thisStation) { | |
| return;//Skip this, bad allocation. | |
| } | |
| NSString *thisStationImageUrl = @"NULL"; | |
| [thisStation setObject:thisStationImageUrl forKey:@"imageUrl"]; | |
| NSMutableArray *thisRepeatorArray = [NSMutableArray array]; | |
| NSMutableDictionary *thisRepeator = [NSMutableDictionary dictionary]; | |
| NSString *thisFrequency = [lineComponents objectAtIndex:Frequency]; | |
| [thisRepeator setObject:thisFrequency forKey:@"frequency"]; | |
| double thisDegreesLatitude = [[lineComponents objectAtIndex:DegreesLongitude] doubleValue]; | |
| double thisDegreesLongitude = [[lineComponents objectAtIndex:DegreesLatitude] doubleValue]; | |
| double thisMinutesLatitude = [[lineComponents objectAtIndex:MinutesLatitude] doubleValue]; | |
| double thisMinutesLongitude = [[lineComponents objectAtIndex:MinutesLongitude] doubleValue]; | |
| double thisSecondsLatitude = [[lineComponents objectAtIndex:SecondsLatitude] doubleValue]; | |
| double thisSecondsLongitude = [[lineComponents objectAtIndex:SecondsLongitude] doubleValue]; | |
| NSNumber *thisLatitude = [NSNumber numberWithDouble:decimalDegrees(thisDegreesLatitude, thisMinutesLatitude, thisSecondsLatitude)]; | |
| NSNumber *thisLongitude = [NSNumber numberWithDouble:decimalDegrees(thisDegreesLongitude, thisMinutesLongitude, thisMinutesLongitude)]; | |
| [thisRepeator setObject:thisLatitude forKey:@"latitude"]; | |
| [thisRepeator setObject:thisLongitude forKey:@"longitude"]; | |
| [thisRepeatorArray addObject:thisRepeator]; | |
| [thisStation setObject:thisRepeatorArray forKey:@"Repeators"]; | |
| //Add station | |
| NSString *thisCallsign = [lineComponents objectAtIndex:Callsign]; | |
| [thisRadioStations setObject:thisStation forKey:thisCallsign]; | |
| }]; | |
| [[fccStations JSONData] writeToFile:@"testOut.json" atomically:YES]; | |
| } | |
| cleanup(); | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment