Git Product home page Git Product logo

caishen's Introduction

Caishen

Travis build status Cocoapods Compatible Carthage compatible Platform Docs

Description

Caishen provides an easy-to-use text field to ask users for payment card information and to validate the input. It serves a similar purpose as PaymentKit, but is developed as a standalone framework entirely written in Swift. Caishen also allows an easy integration with other third-party frameworks, such as CardIO.

![Caishen example](caishen_example.gif)

Requirements

  • iOS 8.0+
  • Xcode 10.0+

Installation

CocoaPods

Caishen is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "Caishen"

Carthage

Caishen is available through Carthage. To install it, simply add the following line to your Cartfile:

github "prolificinteractive/Caishen"

Usage

Example

To run the example project, clone the repo, and run pod install from the Example directory first.


Inside your project

To add a text field for entering card information to a view, either ...

  • ... add a UITextField to your view in InterfaceBuilder and change its class to CardTextField (when using InterfaceBuilder)
  • ... or initiate a CardTextField with one of its initializers (when instantiating from code):
    • init?(coder: aDecoder: NSCoder)
    • init(frame: CGRect)

To get updates about entered card information on your view controller, confirm to the protocol CardTextFieldDelegate set the view controller as cardTextFieldDelegate for the text field:

class MyViewController: UIViewController, CardTextFieldDelegate {
	
	@IBOutlet weak var cardTextField: CardTextField?
	
	override func viewDidLoad() {
		cardTextField?.cardTextFieldDelegate = self
		
		...
	}
	
	func cardTextField(_ cardTextField: CardTextField, didEnterCardInformation information: Card, withValidationResult validationResult: CardValidationResult) {
        // A valid card has been entered, if validationResult == CardValidationResult.Valid
    }
    
    func cardTextFieldShouldShowAccessoryImage(_ cardTextField: CardTextField) -> UIImage? {
        // You can return an image which will be used on cardTextField's accessory button
		 // If you return nil but provide an accessory button action, the unicode character "⇤" is displayed instead of an image to indicate an action that affects the text field.
    }
    
    func cardTextFieldShouldProvideAccessoryAction(_ cardTextField: CardTextField) -> (() -> ())? {
		 // You can return a callback function which will be called if a user tapped on cardTextField's accessory button
		 // If you return nil, cardTextField won't display an accessory button at all.
    }
	
	...

Customizing the text field appearance

CardTextField is mostly customizable like every other UITextField. Setting any of the following standard attributes for a CardTextField (either from code or from interface builder) will affect the text field just like it affects any other UITextField:

Property Type Description
placeholder String? The card number place holder. When using a card number as placeholder, make sure to format it appropriately so it uses the cardNumberSeparator that has been set for the text field (i.e. when using " - " as separator, set a placeholder like "1234 - 1234 - 1234 - 1234").
textColor UIColor? The color of text entered into the CardTextField.
backgroundColor UIColor? The background color of the text field.
font UIFont? The font of the entered text.
secureTextEntry Bool When set to true, any input in the text field will be secure (i.e. masked with "•" characters).
keyboardAppearance UIKeyboardAppearance The keyboard appearance when editing text in the text field.
borderStyle UITextBorderStyle The border style for the text field.

Additionally, CardTextField offers attributes tailored to its purpose (accessible from interface builder as well):

Property Type Description
cardNumberSeparator String? A string that is used to separate the groups in a card number. Defaults to " - ".
viewAnimationDuration Double? The duration for a view animation in seconds when switching between the card number text field and details (month, view and cvc text fields).
invalidInputColor UIColor? The text color for invalid input. When entering an invalid card number, the text will flash in this color and in case of an expired card, the expiry will be displayed in this color as well.

CardIO

CardIO might be among the most powerful tools to let users enter their payment card information. It uses the camera and lets the user scan his or her credit card. However, you might still want to provide users with a visually appealing text field to enter their payment card information, since users might want to restrict access to their camera or simply want to enter this information manually.

In order to provide users with a link to CardIO, you can use a CardTextField's prefillCardInformation method alongside the previously mentioned accessory button:

// 1. Let your view controller confirm to the CardTextFieldDelegate and CardIOPaymentViewControllerDelegate protocol:
class ViewController: UIViewController, CardTextFieldDelegate, CardIOPaymentViewControllerDelegate {
	...
	
	// MARK: - CardTextFieldDelegate
    func cardTextField(_ cardTextField: CardTextField, didEnterCardInformation information: Card, withValidationResult validationResult: CardValidationResult) {
        if validationResult == .Valid {
        	// A valid payment card has been manually entered or CardIO was used to scan one.
        }
    }
    
    // 2. Optionally provide an image for the CardIO button
    func cardTextFieldShouldShowAccessoryImage(_ cardTextField: CardTextField) -> UIImage? {
        return UIImage(named: "cardIOIcon")
    }
    
    // 3. Set the action for the accessoryButton to open CardIO:
    func cardTextFieldShouldProvideAccessoryAction(_ cardTextField: CardTextField) -> (() -> ())? {
        return { [weak self] _ in
            let cardIOViewController = CardIOPaymentViewController(paymentDelegate: self)
            self?.presentViewController(cardIOViewController, animated: true, completion: nil)
        }
    }
    
    // MARK: - CardIOPaymentViewControllerDelegate
    
    // 4. When receiving payment card information from CardIO, prefill the text field with that information:
    func userDidProvideCreditCardInfo(cardInfo: CardIOCreditCardInfo!, inPaymentViewController paymentViewController: CardIOPaymentViewController!) {
        cardTextField.prefillCardInformation(
        	cardInfo.cardNumber, 
        	month: Int(cardInfo.expiryMonth), 
        	year: Int(cardInfo.expiryYear), 
        	cvc: cardInfo.cvv)
        	
        paymentViewController.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func userDidCancelPaymentViewController(paymentViewController: CardIOPaymentViewController!) {
        paymentViewController.dismissViewControllerAnimated(true, completion: nil)
    }
}

Specifying your own card types

CardTextField further contains a CardTypeRegister which maintains a set of different card types that are accepted by this text field. You can create your own card types and add or remove them to or from card number text fields:

struct MyCardType: CardType {
    
    // MARK: - Required

    // The name of your specified card type:
    public let name = "My Card Type"

    // Note: The image that will be displayed in the card number text field's image view when this card type has been detected will load from an asset with the name `cardType.name`.

    // If the Issuer Identification Number (the first six digits of the entered card number) of a card number 
    // starts with anything from 1000 to 1111, the card is identified as being of type "MyCardType":
    public let identifyingDigits = Set(1000...1111)

    // The number of digits expected in the Card Validation Code.
    public let CVCLength = 4

    // MARK: - Optional

    // The grouping of your card number type. The following results in a card number format
    // like "100 - 0000 - 00000 - 000000":
    // Not specifying this will result in a 16 digit number, separated into 4 groups of 4 digits.
    public let numberGrouping = [3, 4, 5, 6]

    /** 
     A boolean flag that indicates whether CVC validation is required for this card type or not.
     Setting this value to false will hide the CVC text field from the `CardTextField` and remove the required validation routine. The default is true.
     */
    public let requiresCVC = true

    /**
     A boolean flag that indicates whether expiry validation is required for this card type or not.
     Setting this value to false will hide the month and year text field from the `CardTextField` and remove the required
     validation routine. The default is true.
     */
    public let requiresExpiry = true
	
    public init() {
		
    }
}

...

class MyViewController: UIViewController, CardTextFieldDelegate {
	
	@IBOutlet weak var cardTextField: CardTextField?
	...
	
	func viewDidLoad() {
		cardTextField?.cardTypeRegister.registerCardType(MyCardType())
	}
	
	...
}

Using the different components of the text field separately

Instead of entering the card number, expiry and CVC in a single text field, it is possible to use single text fields to enter this information separately.

class ViewController: UIViewController, NumberInputTextFieldDelegate, CardInfoTextFieldDelegate {
    
    @IBOutlet weak var cardNumberTextField: NumberInputTextField!
    @IBOutlet weak var monthInputTextField: MonthInputTextField!
    @IBOutlet weak var yearInputTextField: YearInputTextField!
    @IBOutlet weak var cvcInputTextField: CVCInputTextField!
        
    // A card that is not nil when valid information has been entered in the text fields:
    var card: Card? {
        let number = cardNumberTextField.cardNumber
        let cvc = CVC(rawValue: cvcInputTextField.text ?? "")
        let expiry = Expiry(month: monthInputTextField.text ?? "", year: yearInputTextField.text ?? "")
                        ?? Expiry.invalid
        
        let cardType = cardNumberTextField.cardTypeRegister.cardTypeFor(number: cardNumberTextField.cardNumber)
        if cardType.validate(cvc: cvc).union(cardType.validate(expiry: expiry)).union(cardType.validate(number: number)) == .Valid {
            return Card(number: number, cvc: cvc, expiry: expiry)
        } else {
            return nil
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        cardNumberTextField.numberInputTextFieldDelegate = self
        monthInputTextField.cardInfoTextFieldDelegate = self
        yearInputTextField.cardInfoTextFieldDelegate = self
        cvcInputTextField.cardInfoTextFieldDelegate = self
        
        // Set the `deleteBackwardCallbacks` - closures which are called whenever a user hits
        // backspace on an empty text field.
        monthInputTextField.deleteBackwardCallback = { _ in self.cardNumberTextField.becomeFirstResponder() }
        yearInputTextField.deleteBackwardCallback = { _ in self.monthInputTextField.becomeFirstResponder() }
        cvcInputTextField.deleteBackwardCallback = { _ in self.yearInputTextField.becomeFirstResponder() }
    }
    
    func numberInputTextFieldDidComplete(_ numberInputTextField: NumberInputTextField) {
        cvcInputTextField.cardType = numberInputTextField.cardTypeRegister.cardTypeFor(number: numberInputTextField.cardNumber)
        print("Card number: \(numberInputTextField.cardNumber)")
        print(card)
        monthInputTextField.becomeFirstResponder()
    }
    
    func numberInputTextFieldDidChangeText(_ numberInputTextField: NumberInputTextField) {
        
    }
    
    func textField(_ textField: UITextField, didEnterValidInfo: String) {
        switch textField {
        case is MonthInputTextField:
            print("Month: \(didEnterValidInfo)")
            yearInputTextField.becomeFirstResponder()
        case is YearInputTextField:
            print("Year: \(didEnterValidInfo)")
            cvcInputTextField.becomeFirstResponder()
        case is CVCInputTextField:
            print("CVC: \(didEnterValidInfo)")
        default:
            break
        }
        print(card)
    }
    
    func textField(_ textField: UITextField, didEnterPartiallyValidInfo: String) {
        // The user entered information that is not valid but might become valid on further input.
        // Example: Entering "1" for the CVC is partially valid, while entering "a" is not.
    }
    
    func textField(_ textField: UITextField, didEnterOverflowInfo overFlowDigits: String) {
        // This function is used in a CardTextField to carry digits to the next text field.
        // Example: A user entered "02/20" as expiry and now tries to append "5" to the month.
        //          On a card text field, the year will be replaced with "5" - the overflow digit.
    }
    
    // ...
}

Contributing to Caishen

To report a bug or enhancement request, feel free to file an issue under the respective heading.

If you wish to contribute to the project, fork this repo and submit a pull request. Code contributions should follow the standards specified in the Prolific Swift Style Guide.

License

Caishen is Copyright (c) 2017 Prolific Interactive. It may be redistributed under the terms specified in the LICENSE file.

Maintainers

prolific

Caishen is maintained and funded by Prolific Interactive. The names and logos are trademarks of Prolific Interactive.

caishen's People

Contributors

av0c0der avatar dannyvancura avatar fantast1k avatar freak4pc avatar haud avatar htinlinn avatar jamesjsy avatar klein-thibault avatar paulmiard avatar sagarnatekar avatar thibaultklein avatar wenzhi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

caishen's Issues

The tappable area in a CardNumberTextField is too small to tap into

To Reproduce:

To add a text field for entering card information to a view, either ...

  • ... add a UITextField to your view in InterfaceBuilder and change its class to CardNumberTextField (when using InterfaceBuilder)

If you try to tap into the CardNumberTextField, the tap area is too small. You have to tap right beside the card image (probably less than 10 points away) to get it working.

CardIO + NumberInputTextField

How can I combine the last example in this repo (multiple TextFields) with an accessory button that will open CardIO?

Can't get CardTextField to not be first responder

Hi

Thanks for the great project!

By default, my CardTextField object becomes the first responder and I can't seem to disable that feature. I've tried calling resignFirstResponder() on it, but it doesn't seem to work. How can I make it not be the first responder in the first place?

Thanks!

Manual installation

I installed it, how do I get the individual pieces as string so I can set it to user defaults

Docset

The documentation coverage on the Docset should be much higher.

There should be more comments throughout the whole project in proper Swift Markup Syntax.

new to library

i'm writing an app using swift 3

i added this framework to my project using carthage. everything appears to be fine.
however in interface builder, i can't set the class to CardTextField

I get an error when running the application
Unknown class CardTextField in Interface Builder file

any help would be appreciated

Caishen 1.5.0 crashes when prefilling partial card info.

After performing scan card with Card.io I'm performing :
image

This worked well in all previous version.
Currently it crashes in NumberInputTextField.swift line 96. It seems the textFieldTextFormatted is an empty string despite me passing a full credit card string.

This didn't crash in previous version.
Thoughts?

CardTextField prefill not prefilling month, year and cvc

Hi,

I'm trying to use Caishen combined with CashIO SDK and couldn't find a way to make the prefill func work (under swift 3.0 and XCode 8).

Currently, I got

public func userDidProvide(_ cardInfo: CardIOCreditCardInfo!, in paymentViewController: CardIOPaymentViewController!) {
    cardTextField.prefill(cardInfo.cardNumber,
                          month: Int(cardInfo.expiryMonth),
                          year: Int(cardInfo.expiryYear),
                          cvc: cardInfo.cvv)
    paymentViewController.dismiss(animated: true, completion: nil)
}

The only field that changes is the cardNumberField.

Any idea why?

Thanks

Does not conform to CardTextFieldDelegate

@DannyVancura
This error kept bugging me while following the instructions. It existed in this delegate method declaration.

func cardTextField(cardTextField: CardTextField, didEnterCardInformation information: Card, withValidationResult validationResult: CardValidationResult?) {
        // A valid card has been entered, if information is not nil and validationResult == CardValidationResult.Valid
    } 

The problem was that

CardValidationResult?

is an optional When I removed the ? to

CardValidationResult

the error disappeared. Perhaps a reason why?

I can't change the card number separator

I can't change the card number separator.

i tried:
cardTextField.numberInputTextField.cardNumberSeparator = "-"
and:
cardTextField.cardNumberSeparator = "-"

i get the following error:
Thread 1: EXC_BAD_ACCESS
at CardNumberFormater.swift in public func format(cardNumber: String) -> String
on the following line:
regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options())

Can't type anything into the custom TextFields.

I just set my TextFields to correspond to the examples (e.g. CVCInputTextField) and when I try to type inside those, nothing happens (cursor doesn't move and I can't see the text). Moreover, the keyboard doesn't change to the corresponding input type.

If I try to type something in other non-custom Text Fields inside my UI, it works.

Demo project Buy Now does nothing

Hi,

When tapping on the Buy Now button nothing happens and the console prints this error:

<UIVisualEffectView 0x7cb68040> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

A quick fix to unblock the QA is to change the background color to white in Main.storyboard.

Thanks!

Error on installing on swift 3

Hi,

I tried my best before posting my answer here ... but still did not work ..

pod 'Caishen', :git => 'https://github.com/prolificinteractive/Caishen.git', :branch => 'swift-3.0'

but I receive this error:
[!] Error installing Caishen
[!] /usr/bin/git clone https://github.com/prolificinteractive/Caishen.git /var/folders/3f/hlddm2z55_91b6hx68g2vflw0000gn/T/d20161229-86999-1vt21f1 --template= --single-branch --depth 1 --branch swift-3.0

Cloning into '/var/folders/3f/hlddm2z55_91b6hx68g2vflw0000gn/T/d20161229-86999-1vt21f1'...
warning: Could not find remote branch swift-3.0 to clone.
fatal: Remote branch swift-3.0 not found in upstream origin

How to get the swipe animation programmatically?

Hi,

I noticed that when you entered a valid credit card number, exp date and CVV and you go back to the credit card field, exp date and CVV fields disappear. One way to see them again is to swipe in the text field, but I'd like to programmatically trigger the same animation when the card number text field becomes first responder. Any ideas on how to do that?

Thanks!

is it possible to use Caishen components separately

I have different design from what Caishen provide right now and I wanna check if I can use the textFields separately and take advantage of the current component because it provides complete solution regarding the validation, support different card types... etc
Thank you!

CardTypeRegister doesn't have to be a singleton

Hi,

CardTypeRegister doesn't have to be a singleton, it could just live with the instance of the text field. You can make the init public, and also create a constant for the default credit card types array that you use as a public variable.

xcode 9 swift 4 errors

Hi,
I migrated from swift 3 to 4 and i got errors related to swift 4 syntax
you will update the pod for swift 4 ?

Thanks,

Card.io + Prefill Causing Keyboard to pop up

Using Card.io method 'userDidProvide' I call cardTexField.prefill to populate the cardTextField with values. When I hit done on the paymentViewController, prefill is called the keyboard reappears to fill out values I've already provided. Already tried a number of resignFirstResponder fixes and nothing worked.

CardNumberTextField delegate not passing CardValidationResult until all fields are filled

In the delegate function:

func cardNumberTextField(cardNumberTextField: CardNumberTextField,
                             didEnterCardInformation information: Card?,
                                                     withValidationResult validationResult: CardValidationResult?)

the CardValidationResult is only set once the CC number, expiration date and CVC code are set. The expected result is that the CardValidationResult will raise issues as they come up with every keystroke.

For example, if i am entering a CC number and enter 1111-11, on the next tap of 1, I expect that CardValidationResult will not be nil, because the text color changes to red, hinting that there is a validation issue.

card.io won't present app crashes

The app crashes at this line
let cardIOViewController = CardIOPaymentViewController(paymentDelegate: self)

It's not recognizing paymentdelegate

Validate Card on pre-fill

After pre-filling fields with CardIO, didEnterCardInformation is not called.
Some actions are taken after a successful validation, such as enabling a "Submit" button.

How would I force textfield to validate and call the didEnterCardInformation delegate method?

no pod spec found

Can you help me. I'm trying to pod install but your pods are failing for me

Card Number Text Field Not Responsive

Once all card info is entered and the cardNumberTextField is tapped (not swiped), the CardTextField will not transition back to the full cardNumberTextField mode or even allow editing of the card number.

NumberInputTextField text color not working with prefillInformation

I'm having problems setting textColor to NumberInputTextField when using with prefillInformation with Card.IO integration. I used very hacky workaround for this:

cardNumberInput.textField(cardNumberInput, shouldChangeCharactersInRange: NSMakeRange(0, cardNumberInput.text!.characters.count), replacementString: cardNumberInput.text!)

I guess there is a bigger issue behind this caused by the use of _textColor because this seemed to be to only way to trigger super.textColor change.

Visual Effect error

I get this error when ever I run the example project.
<UIVisualEffectView 0x7f925b803be0> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

Allow to disable Luhn test for a custom card type

Hi,
Would it be possible to have the option to disable Luhn test in a custom card type? Some cards don't require this validation but Caishen doesn't allow this functionality currently.

I would suggest to create a boolean in CardType that is checked before Luhn test is applied.

Thanks!

xcode 9 beta 4 Build failed pod

StringExtension.swift

    func NSRangeFrom(_ range : Range<String.Index>) -> NSRange {
        let utf16view = self.utf16
        let from = String.UTF16View.Index(range.lowerBound, within: utf16view)
        let to = String.UTF16View.Index(range.upperBound, within: utf16view)
        return NSMakeRange(utf16view.startIndex.distance(to: from), from.distance(to: to))
    }

NSMakeRange(utf16view.startIndex.distance(to: from), from.distance(to: to))
Value of optional type 'String.UTF16View.Index?' (aka 'Optional<String.Index>') not unwrapped; did you mean to use '!' or '?'?

Swift 3 compatibility

Hello ! I Really appreciate your work guys. Is there any chances to know when you will release swift 3 compatibility ?

Card image for custom card type

Hi there,

Is there an easy way to provide a custom image for a custom card type?

I noticed that I could "hack" by having the card image name equal to the card type name, but imageForCardType is using self as the bundle, which returns nil if the image is contained in the project bundle and not the pod bundle.

public func imageForCardType(cardType: CardType) -> UIImage? {
    return UIImage(named: cardType.name, inBundle: self, compatibleWithTraitCollection: nil)
}

Thank you for your help!

Caishen - IQKeyboardManagerSwift

Currently, I am using Caishen and IQKeyboardManager to move between text fields on a custom payment view screen. Generally it works pretty well, but for some reason i can’t get it to work when moving from a regular UITextField to a CardTextField, and vice versa.

Based on a quick glance, it appears that CardTextField rejects `becomeFirstResponder. Is it possible for someone to take a look?

cardTextFieldDelegate prevents UIViewController dealloc

I am using a CardTextField and when i set the delegate as my viewController the controller never deallocs. If i comment the line that i set delegate the viewController deallocs fine. I think the delegate may be not using weak reference, can anyone check this bug please?

Code:
cardTextField.cardTextFieldDelegate = self

self is the viewController

CardValidationResult { } characters in description

Currently there is no way to get plain text error messages from a CardValidationResult. The results are put into a JSON like structure, as seen in the following image.

Card Validation Result

Would it be possible to have a function or property that returns an array of strings, or update description to remove the { \t and } characters, and the initial new line character?

CardNumberFormatter Regex Broken

Example, American Express, debug output with a card number of "37671234561234"

CardType: AmericanExpress(name: "Amex", CVCLength: 4, numberGrouping: [4, 6, 5], identifyingDigits: Set([37, 34])), groups: [4, 6, 5]
Pattern: (\d{1,4})(\d{1,6})?(\d{1,5})?
Regex: <NSRegularExpression: 0x13772f8d0> (\d{1,4})(\d{1,6})?(\d{1,5})? 0x0
Formatted: 3767 1234 5612 34

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.