<commit_before>import UIKit
import CoreData

class DittoStore : NSObject {
    
    let MAX_CATEGORIES = 8
    let PRESET_CATEGORIES = ["Instructions", "Driving", "Business", "Tinder"]
    let PRESET_DITTOS = [
        "Instructions": [
            "Welcome to Ditto! 👋",
            "Add Ditto in Settings > General > Keyboard > Keyboards.",
            "You must allow full access for Ditto to work properly. After you've added the Ditto keyboard, select it, and turn on Allow Full Access.",
            "We DO NOT access ANYTHING that you type on the keyboard.",
            "Everything is saved privately on your device.",
            "Use the Ditto app to customize your dittos.",
            "Add a triple underscore ___ to your ditto to control where your cursor lands.",
            "You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try!",
            "Hold down a keyboard tab to uncover the category, and swipe between tabs for quick access."
        ],
        
        "Driving": [
            "I'm driving, can you call me?",
            "I'll be there in ___ minutes!",
            "What's the address?",
            "Can't text, I'm driving."
        ],
        
        "Business": [
            "Hi ___,\n\nIt was great meeting you today. I'd love to chat in more detail about possible business opportunities. Please let me know your availability.\n\nBest,\n<NAME>",
            "My name is Asaf, and I work at Shmoogle on the search team. We are always looking for talented candidates to join our team, and with your impressive background, we think you could be a great fit. Please let me know if you are interested, and if so, your availability to chat this week."
        ],
        
        "Tinder": [
            "I'm not a photographer, but I can picture us together.",
            "Was your dad a thief? Because someone stole the stars from the sky and put them in your eyes.",
            "Do you have a Band-Aid? Because I just scraped my knee falling for you."
        ]
    ]
    
    static var managedObjectModel: NSManagedObjectModel = {
        let modelURL = NSBundle.mainBundle().URLForResource("Ditto", withExtension: "momd")!
        return NSManagedObjectModel(contentsOfURL: modelURL)!
    }()
    
    static var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        
        let directory = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.io.asaf.ditto")
        let storeURL = directory?.URLByAppendingPathComponent("Ditto.sqlite")
        
        let options = [
            NSMigratePersistentStoresAutomaticallyOption: NSNumber(bool: true),
            NSInferMappingModelAutomaticallyOption: NSNumber(bool: true)
        ]
        
        let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
        
        var err: NSError? = nil
        if persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options, error: &err) == nil {
            fatalError(err!.localizedDescription)
        }
        
        return persistentStoreCoordinator
        
    }()
    
    static var managedObjectContext: NSManagedObjectContext = {
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
        return managedObjectContext
    }()
    
    //===================
    // MARK: Persistence
    
    lazy var context: NSManagedObjectContext = {
        return DittoStore.managedObjectContext
    }()
    
    func save() {
        var err: NSError? = nil
        if !DittoStore.managedObjectContext.save(&err) {
            fatalError(err!.localizedDescription)
        }
    }
    
    func createProfile() -> Profile {
        let profile = NSEntityDescription.insertNewObjectForEntityForName("Profile", inManagedObjectContext: DittoStore.managedObjectContext) as! Profile
        for categoryName in PRESET_CATEGORIES {
            var category = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: DittoStore.managedObjectContext) as! Category
            category.profile = profile
            category.title = categoryName
            
            for dittoText in PRESET_DITTOS[categoryName]! {
                var ditto = NSEntityDescription.insertNewObjectForEntityForName("Ditto", inManagedObjectContext: DittoStore.managedObjectContext) as! Ditto
                ditto.category = category
                ditto.text = dittoText
            }
        }
        save()
        
        return profile
    }
    
    func getProfile() -> Profile {
        let fetchRequest = NSFetchRequest(entityName: "Profile")
        var error: NSError?
        if let profiles = DittoStore.managedObjectContext.executeFetchRequest(fetchRequest, error: &error) {
            if profiles.count > 0 {
                return profiles[0] as! Profile
            } else {
                return self.createProfile()
            }
        } else {
            fatalError(error!.localizedDescription)
        }
        
    }
    
    //===============
    // MARK: Getters
    
    func getCategories() -> [String] {
        return Array(getProfile().categories).map({ (category) in
            let c = category as! Category
            return c.title<commit_msg>Adding migration of old dittos from version 1<commit_after>import UIKit
import CoreData

class DittoStore : NSObject {
    
    let MAX_CATEGORIES = 8
    let PRESET_CATEGORIES = ["Instructions", "Driving", "Business", "Tinder"]
    let PRESET_DITTOS = [
        "Instructions": [
            "Welcome to Ditto! 👋",
            "Add Ditto in Settings > General > Keyboard > Keyboards.",
            "You must allow full access for Ditto to work properly. After you've added the Ditto keyboard, select it, and turn on Allow Full Access.",
            "We DO NOT access ANYTHING that you type on the keyboard.",
            "Everything is saved privately on your device.",
            "Use the Ditto app to customize your dittos.",
            "Add a triple underscore ___ to your ditto to control where your cursor lands.",
            "You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try! You can expand long dittos within the keyboard by holding them down. Go ahead and give this one a try!",
            "Hold down a keyboard tab to uncover the category, and swipe between tabs for quick access."
        ],
        
        "Driving": [
            "I'm driving, can you call me?",
            "I'll be there in ___ minutes!",
            "What's the address?",
            "Can't text, I'm driving."
        ],
        
        "Business": [
            "Hi ___,\n\nIt was great meeting you today. I'd love to chat in more detail about possible business opportunities. Please let me know your availability.\n\nBest,\n<NAME>",
            "My name is Asaf, and I work at Shmoogle on the search team. We are always looking for talented candidates to join our team, and with your impressive background, we think you could be a great fit. Please let me know if you are interested, and if so, your availability to chat this week."
        ],
        
        "Tinder": [
            "I'm not a photographer, but I can picture us together.",
            "Was your dad a thief? Because someone stole the stars from the sky and put them in your eyes.",
            "Do you have a Band-Aid? Because I just scraped my knee falling for you."
        ]
    ]
    
    let defaults = NSUserDefaults(suiteName: "group.io.asaf.ditto")!
    
    static var managedObjectModel: NSManagedObjectModel = {
        let modelURL = NSBundle.mainBundle().URLForResource("Ditto", withExtension: "momd")!
        return NSManagedObjectModel(contentsOfURL: modelURL)!
    }()
    
    static var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        
        let directory = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.io.asaf.ditto")
        let storeURL = directory?.URLByAppendingPathComponent("Ditto.sqlite")
        
        let options = [
            NSMigratePersistentStoresAutomaticallyOption: NSNumber(bool: true),
            NSInferMappingModelAutomaticallyOption: NSNumber(bool: true)
        ]
        
        let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
        
        var err: NSError? = nil
        if persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options, error: &err) == nil {
            fatalError(err!.localizedDescription)
        }
        
        return persistentStoreCoordinator
        
    }()
    
    static var managedObjectContext: NSManagedObjectContext = {
        var managedObjectContext = NSManagedObjectContext()
        managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
        return managedObjectContext
    }()
    
    //===================
    // MARK: Persistence
    
    lazy var context: NSManagedObjectContext = {
        return DittoStore.managedObjectContext
    }()
    
    func save() {
        var err: NSError? = nil
        if !DittoStore.managedObjectContext.save(&err) {
            fatalError(err!.localizedDescription)
        }
    }
    
    func createProfile() -> Profile {
        let profile = NSEntityDescription.insertNewObjectForEntityForName("Profile", inManagedObjectContext: DittoStore.managedObjectContext) as! Profile
        for categoryName in PRESET_CATEGORIES {
            var category = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: DittoStore.managedObjectContext) as! Category
            category.profile = profile
            category.title = categoryName
            
            for dittoText in PRESET_DITTOS[categoryName]! {
                var ditto = NSEntityDescription.insertNewObjectForEntityForName("Ditto", inManagedObjectContext: DittoStore.managedObjectContext) as! Ditto
                ditto.category = category
                ditto.text = dittoText
            }
        }
        
        // Migrate dittos from V1
        if let dittos = defaults.arrayForKey("dittos") as? [String] {
            var category = NSEntityDescription.insertNewObjectForEntityForName("Category", inManagedObjectContext: DittoStore.managedObjectContext) as! Category
            category.profile = profile
            category.title = "Saved"
            for dittoText in dittos {
                var ditto = NSEntityDescription.insertNewObjectForEntityForName("Ditto", inManagedObjectContext: DittoStore.managedObjectContext) as! Ditto
                ditto.category = category
                ditto.text = dittoText
            }
        }
        
        save()
        
        return profile
    }
    
    func getProfile() -> Profile {
        let fetchRequest = NSFetchRequest(entityName: "Profile")
        var error: NSError?
        if let profiles = DittoStore.managedObjectContext.executeFetchRequest(fetchRequest, error: &error) {
            if profiles.count > 0 {
                return profiles[0] as! Profile
            } else {
                return self.createProfile()
            }
        } else {
            fatalError(error!.localizedDescription)
        }
        
    }
    
    //===============
    // MARK: Getters
    
    func getCategories() -> [String] {
        return Array(getProfile().categories).map({ (category) in
            let c = category as! Category
            return c.title
{'fraction_non_alphanumeric': 0.07733137350971746, 'fraction_numerical': 0.0006532745386248571, 'mean_word_length': 2.3944013303769403, 'pattern_counts': {'":': 8, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4785458', 'n_tokens_mistral': 3157, 'n_tokens_neox': 3061, 'n_words': 1042}