197 lines
5.8 KiB
Plaintext
197 lines
5.8 KiB
Plaintext
#import "LanguageModelManager.h"
|
|
#import <fstream>
|
|
#import <iostream>
|
|
#import <set>
|
|
#import "OVStringHelper.h"
|
|
#import "OVUTF8Helper.h"
|
|
|
|
using namespace std;
|
|
using namespace Formosa::Gramambular;
|
|
using namespace OpenVanilla;
|
|
|
|
static const int kUserOverrideModelCapacity = 500;
|
|
static const double kObservedOverrideHalflife = 5400.0; // 1.5 hr.
|
|
|
|
FastLM globalLanguageModel;
|
|
FastLM globalLanguageModelPlainBopomofo;
|
|
FastLM globalUserPhraseLanguageModel;
|
|
FastLM globalUserExcludedPhrasesMcBopomofo;
|
|
FastLM globalUserExcludedPhrasesPlainBopomofo;
|
|
McBopomofo::UserOverrideModel globalUserOverrideModel(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
|
|
|
@implementation LanguageModelManager
|
|
|
|
static bool LTLoadLanguageModelFile(NSString *filenameWithoutExtension, FastLM &lm)
|
|
{
|
|
Class cls = NSClassFromString(@"McBopomofoInputMethodController");
|
|
NSString *dataPath = [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"];
|
|
bool result = lm.open([dataPath UTF8String]);
|
|
return (BOOL)result;
|
|
}
|
|
|
|
+ (void)loadDataModels
|
|
{
|
|
bool dataOpenResult = LTLoadLanguageModelFile(@"data", globalLanguageModel);
|
|
if (!dataOpenResult) {
|
|
NSLog(@"Failed to open language model.");
|
|
}
|
|
bool plainBpmfOpenResult = LTLoadLanguageModelFile(@"data-plain-bpmf", globalLanguageModelPlainBopomofo);
|
|
if (!plainBpmfOpenResult) {
|
|
NSLog(@"Failed to open language model for plain bpmf.");
|
|
}
|
|
}
|
|
|
|
+ (void)loadUserPhrasesModel
|
|
{
|
|
globalUserPhraseLanguageModel.close();
|
|
globalUserExcludedPhrasesMcBopomofo.close();
|
|
globalUserExcludedPhrasesPlainBopomofo.close();
|
|
|
|
bool result = false;
|
|
|
|
result = globalUserPhraseLanguageModel.open([[self userPhrasesDataPathMcBopomofo] UTF8String]);
|
|
if (!result) {
|
|
NSLog(@"Failed to open user phrases. %@", [self userPhrasesDataPathMcBopomofo]);
|
|
}
|
|
result = globalUserExcludedPhrasesMcBopomofo.open([[self excludedPhrasesDataPathMcBopomofo] UTF8String]);
|
|
if (!result) {
|
|
NSLog(@"Failed to open excluded phrases McBopomofo. %@", [self excludedPhrasesDataPathMcBopomofo]);
|
|
}
|
|
|
|
result = globalUserExcludedPhrasesPlainBopomofo.open([[self excludedPhrasesDataPathPlainBopomofo] UTF8String]);
|
|
if (!result) {
|
|
NSLog(@"Failed to open excluded phrases Plain Bopomofo. %@", [self excludedPhrasesDataPathPlainBopomofo]);
|
|
}
|
|
}
|
|
|
|
+ (BOOL)checkIfUserDataFolderExists
|
|
{
|
|
NSString *folderPath = [self dataFolderPath];
|
|
BOOL isFolder = NO;
|
|
BOOL folderExist = [[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:&isFolder];
|
|
if (folderExist && !isFolder) {
|
|
NSError *error = nil;
|
|
[[NSFileManager defaultManager] removeItemAtPath:folderPath error:&error];
|
|
if (error) {
|
|
NSLog(@"Failed to remove folder %@", error);
|
|
return NO;
|
|
}
|
|
folderExist = NO;
|
|
}
|
|
if (!folderExist) {
|
|
NSError *error = nil;
|
|
[[NSFileManager defaultManager] createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:&error];
|
|
if (error) {
|
|
NSLog(@"Failed to create folder %@", error);
|
|
return NO;
|
|
}
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
+ (BOOL)checkIfFileExist:(NSString *)filePath
|
|
{
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
|
BOOL result = [[@"" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:YES];
|
|
if (!result) {
|
|
NSLog(@"Failed to write file");
|
|
return NO;
|
|
}
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
+ (BOOL)checkIfUserLanguageModelFilesExist
|
|
{
|
|
if (![self checkIfUserDataFolderExists]) {
|
|
return NO;
|
|
}
|
|
if (![self checkIfFileExist:[self userPhrasesDataPathMcBopomofo]]) {
|
|
return NO;
|
|
}
|
|
if (![self checkIfFileExist:[self excludedPhrasesDataPathMcBopomofo]]) {
|
|
return NO;
|
|
}
|
|
if (![self checkIfFileExist:[self excludedPhrasesDataPathPlainBopomofo]]) {
|
|
return NO;
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
+ (BOOL)writeUserPhrase:(NSString *)userPhrase
|
|
{
|
|
if (![self checkIfUserLanguageModelFilesExist]) {
|
|
return NO;
|
|
}
|
|
|
|
NSString *currentMarkedPhrase = [userPhrase stringByAppendingString:@"\n"];
|
|
|
|
NSString *path = [self userPhrasesDataPathMcBopomofo];
|
|
NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:path];
|
|
if (!file) {
|
|
return NO;
|
|
}
|
|
[file seekToEndOfFile];
|
|
NSData *data = [currentMarkedPhrase dataUsingEncoding:NSUTF8StringEncoding];
|
|
[file writeData:data];
|
|
[file closeFile];
|
|
|
|
[self loadUserPhrasesModel];
|
|
return YES;
|
|
}
|
|
|
|
+ (NSString *)dataFolderPath
|
|
{
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES);
|
|
NSString *appSupportPath = [paths objectAtIndex:0];
|
|
NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"McBopomofo"];
|
|
return userDictPath;
|
|
}
|
|
|
|
+ (NSString *)userPhrasesDataPathMcBopomofo
|
|
{
|
|
return [[self dataFolderPath] stringByAppendingPathComponent:@"data.txt"];
|
|
}
|
|
|
|
+ (NSString *)excludedPhrasesDataPathMcBopomofo
|
|
{
|
|
return [[self dataFolderPath] stringByAppendingPathComponent:@"exclude-phrases.txt"];
|
|
}
|
|
|
|
+ (NSString *)excludedPhrasesDataPathPlainBopomofo
|
|
{
|
|
return [[self dataFolderPath] stringByAppendingPathComponent:@"exclude-phrases-plain-bpmf.txt"];
|
|
}
|
|
|
|
+ (FastLM *)languageModelMcBopomofo
|
|
{
|
|
return &globalLanguageModel;
|
|
}
|
|
|
|
+ (FastLM *)languageModelPlainBopomofo
|
|
{
|
|
return &globalLanguageModelPlainBopomofo;
|
|
}
|
|
|
|
+ (FastLM *)userPhraseLanguageModel
|
|
{
|
|
return &globalUserPhraseLanguageModel;
|
|
}
|
|
|
|
+ (FastLM *)excludedPhrasesLanguageModelMcBopomofo
|
|
{
|
|
return &globalUserExcludedPhrasesMcBopomofo;
|
|
}
|
|
|
|
+ (FastLM *)excludedPhrasesLanguageModelPlainBopomofo
|
|
{
|
|
return &globalUserExcludedPhrasesPlainBopomofo;
|
|
}
|
|
|
|
+ (McBopomofo::UserOverrideModel *)userOverrideModel
|
|
{
|
|
return &globalUserOverrideModel;
|
|
}
|
|
|
|
@end
|