forked from torifat/iAvro
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSuggestion.m
More file actions
169 lines (148 loc) · 6.79 KB
/
Suggestion.m
File metadata and controls
169 lines (148 loc) · 6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//
// AvroKeyboard
//
// Created by Rifat Nabi on 6/28/12.
// Copyright (c) 2012 OmicronLab. All rights reserved.
//
#import "Suggestion.h"
#import "AvroParser.h"
#import "RegexParser.h"
#import "NSString+Levenshtein.h"
#import "RegexKitLite.h"
#import "AvroKeyboard-Swift.h"
static Suggestion* sharedInstance = nil;
@implementation Suggestion
+ (Suggestion *)sharedInstance {
if (sharedInstance == nil) {
[[self alloc] init]; // assignment not done here, see allocWithZone
}
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)zone {
if (sharedInstance == nil) {
sharedInstance = [super allocWithZone:zone];
return sharedInstance; // assignment and return on first allocation
}
return nil; //on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (instancetype)init {
self = [super init];
if (self) {
_suggestions = [[NSMutableArray alloc] initWithCapacity:0];
}
return self;
}
- (NSMutableArray*)getList:(NSString*)term {
if (term && term.length == 0) {
return _suggestions;
}
// Suggestions from Default Parser
NSString* paresedString = [[AvroParser sharedInstance] parse:term];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"IncludeDictionary"]) {
// Saving humanity by reducing a few CPU cycles
[_suggestions addObjectsFromArray:[[CacheManager shared] arrayForKey:term]];
if (_suggestions && _suggestions.count == 0) {
// Suggestions form AutoCorrect
NSString* autoCorrect = [[AutoCorrect shared] find:term];
if (autoCorrect) {
[_suggestions addObject:autoCorrect];
}
// Suggestions from Dictionary
NSArray* dicList = [[Database shared] find:term];
if (dicList) {
// Remove autoCorrect if it is already in the dictionary
// PROPOSAL: don't add the autoCorrect, which matches with the dictionary entry
if (autoCorrect && [dicList containsObject:autoCorrect]) {
[_suggestions removeObjectIdenticalTo:autoCorrect];
}
// Sort dicList based on edit distance
NSArray* sortedDicList = [dicList sortedArrayUsingComparator:^NSComparisonResult(id left, id right) {
int dist1 = [paresedString computeLevenshteinDistanceWithString:(NSString*)left];
int dist2 = [paresedString computeLevenshteinDistanceWithString:(NSString*)right];
if (dist1 < dist2) {
return NSOrderedAscending;
}
else if (dist1 > dist2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
[_suggestions addObjectsFromArray:sortedDicList];
}
[[CacheManager shared] setArray:[_suggestions copy] forKey:term];
}
// Suggestions with Suffix
NSInteger i;
BOOL alreadySelected = FALSE;
[[CacheManager shared] removeAllBase];
for (i = term.length-1; i > 0; --i) {
NSString* suffix = [[Database shared] banglaForSuffix:[term substringFromIndex:i].lowercaseString];
if (suffix) {
NSString* base = [term substringToIndex:i];
NSArray* cached = [[CacheManager shared] arrayForKey:base];
NSString* selected;
if (!alreadySelected) {
// Base user selection
selected = [[CacheManager shared] stringForKey:base];
}
// This should always exist, so it's just a safety check
if (cached) {
for (NSString *item in cached) {
// Skip AutoCorrect English Entry
if ([base isEqualToString:item]) {
continue;
}
NSString* word;
// Again saving humanity cause I'm Superman, no I'm not drunk or on weed :D
NSInteger cutPos = item.length - 1;
NSString* itemRMC = [item substringFromIndex:cutPos]; // RMC is Right Most Character
NSString* suffixLMC = [suffix substringToIndex:1]; // LMC is Left Most Character
// BEGIN :: This part was taken from http://d.pr/zTmF
if ([self isVowel:itemRMC] && [self isKar:suffixLMC]) {
word = [NSString stringWithFormat:@"%@\u09df%@", item ,suffix];
}
else {
if ([itemRMC isEqualToString:@"\u09ce"]) {
word = [NSString stringWithFormat:@"%@\u09a4%@", [item substringToIndex:cutPos], suffix];
}
else if ([itemRMC isEqualToString:@"\u0982"]) {
word = [NSString stringWithFormat:@"%@\u0999%@", [item substringToIndex:cutPos], suffix];
} else {
word = [NSString stringWithFormat:@"%@%@", item, suffix];
}
}
// END
// Reverse Suffix Caching
[[CacheManager shared] setBase:@[base, item] forKey:word];
// Check that the WORD is not already in the list
if (![_suggestions containsObject:word]) {
// Intelligent Selection
if (!alreadySelected && selected && [item isEqualToString:selected]) {
if (![[CacheManager shared] stringForKey:term]) {
[[CacheManager shared] setString:word forKey:term];
}
alreadySelected = TRUE;
}
[_suggestions addObject:word];
}
}
}
}
}
}
if ([_suggestions containsObject:paresedString] == NO) {
[_suggestions addObject:paresedString];
}
return _suggestions;
}
- (BOOL)isKar:(NSString*)letter {
return [letter isMatchedByRegex:@"^[\u09be\u09bf\u09c0\u09c1\u09c2\u09c3\u09c7\u09c8\u09cb\u09cc\u09c4]$"];
}
- (BOOL)isVowel:(NSString*)letter {
return [letter isMatchedByRegex:@"^[\u0985\u0986\u0987\u0988\u0989\u098a\u098b\u098f\u0990\u0993\u0994\u098c\u09e1\u09be\u09bf\u09c0\u09c1\u09c2\u09c3\u09c7\u09c8\u09cb\u09cc]$"];
}
@end