Giter Site home page Giter Site logo

tommens / calculator-cucumber Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 7.0 1.31 MB

This repository is used for teaching purposes at the University of Mons. It contains Java code for computing arithmetic expressions. The code uses design patterns and is accompanied with JavaDoc, unit tests and BDD scenarios. We have also paid particular attention to code quality.

License: GNU General Public License v3.0

Java 93.19% Gherkin 6.81%
bdd cucumber cucumber-java java java11 javadoc junit maven mvn test-automation testing

calculator-cucumber's People

Contributors

codacy-badger avatar damienlegay avatar dependabot[bot] avatar gauvaind avatar github-actions[bot] avatar step-security-bot avatar tommens avatar yazgoo avatar

Watchers

 avatar

calculator-cucumber's Issues

[FEATURE] Suporting real numbers

Describe the new functionality you would like to see
The current version of this code only provides support for integer arithmetic. We also would like to also have support for arithmetics on decimal/real numbers. One possibility would be to use float or double as internal type for such numbers, but I strongly suggest to use something like java.math.BigDecimal, which allows for artibrary-precision decimal numbers and also provides operations for arithmetic, scale manipulation, rounding, comparison, hashing, and format conversion.
Implementing this functionality should also include the following ones:

Very large or very small decimal numbers should be expressible more compactly using the scientific notation or E-notation. for example, 6.022E23 would be considered as is equivalent to 6.022×10^23, which would be written as 6022 followed by 20 zeroes in "traditional" notation of natural numbers. Similarly, 1.6E-35 would be considered equivalent to 1.6×10^(−35) which would be written as 0.00...00016 (with lots of zeroes after the floating point of the decimal number).
It should be possible to specify the precision of these decimal numbers (i.e., how many significant digits of a real number will be encoded). This precision can be fixed when constructing a calculator, but the application should be able to be configured with a given precision for decimal numbers. (It is left open for discussion whether it should be possible from within a running calculator itself to change the precision.)
When supporting arithmetics on real numbers, care should be taken when carrying out operations that may result in an error. E.g. 0.0 / 0.0 is a NaN, i.e. an undefined number; 1.0/0.0 is either +infinity or a division by zero error, depending on whether infinity is allowed/supported by the calculator; -1.0/0.0 would be -infinity or a division by zero error; taking the square root of a negative number is not allowed (NaN); taking the logarithm of a negative value is not allowed (NaN) and so on. A clean, generic and reusable solution needs to be found for all such cases; knowing that the same types of problems may also occur for other number domains (integer values; fractions; complex number; ...)
As supported on most scientific calculators, it should be possible to use and convert numbers from degrees or radians (the use of radians if often more intuitive and useful when working frequently with trigonometric functions like sin, cos, and so on).

[FEATURE] More kinds of arithmetic operations

Describe the new functionality you would like to see
The current calculator is too basic, since it only provides support for +, *, / and -. Many other types of mathematical operations are useful and needed for a full-fledged calculator. To get more inspiration for other types of operations one can also look at what typical scientific calculator machines provide. One could for example rely on java.lang.Math to implement other basic numeric operations, such as the power function, exponential, logarithm, square root, and all trigonometric functions (sin, cos, tan, their inverses and more). Which types of operations to provide will depend on the types of numbers supported by the calculator.

For the real number domain, it would be desirable to implement at least the following functions: logarithm, square root, all trigonometric functions (e.g., sin, cos, tan, their inverses and more), the inverse function (1/x), and support for frequently used constants such as e and Pi.
For the integer number domain, it would be desirable to implement support for modular arithmetics.
Regardless of the considered number domain, it would be useful to implement a pseudorandom generator. For testing purposes, it should be possible to give a random seed to the random generator can be tested deterministically.

For the integer number domain: Given an integer as input, the random generator will provide a random integer between 0 and the integer provided as input.
For the real number domain: No value needs to be provided as input, the random generator will always provide a real value between 0 and 1.

[FEATURE] Web-based GUI for calculator

Describe the new functionality you would like to see
Create a web-based GUI for the calculator application, based on JavaScript technology, and relying on the REST API provided through the feature request in issue #120.

Additional context
Many different frameworks, libraries and tools exist for developing web-based GUIs based on JavaScript technology.

[FEATURE] Supporting Boolean logic

Describe the new functionality you would like to see
It would be nice (and not too difficult) to add support for Boolean expressions (we can assume that true is represented as 0, and false is represented as 1), Boolean operations (e.g., and, or, not, implication, equivalence, xor); and Boolean algebra (https://en.wikipedia.org/wiki/Boolean_algebra). One could also consider using Boolean laws to replace logic expressions by equivalent ones.

[FEATURE] Java-based GUI for calculator

In the current implementation, arithmetic expressions need to be build manually, from scratch. A real calculator has a graphical user interface (GUI) through which you can enter expressions by pressing the buttons of your calculator, and getting the result of evaluating your expression that will be shown on the calculator's display screen.

To create this GUI, you should select and motivate the most appropriate framework for doing so. Many Java GUI frameworks are available: Oracle JavaFX (successor of Swing), Oracle Swing (successor and extension of AWT), Apache Pivot (open source framework), Eclipse SWT (also open source), ...

[FEATURE] Expression parser

Describe the new functionality you would like to see
In order to easily write expressions as strings, and convert them into abstract syntax trees that can be processed for evaluation, we need an expression parser:

  • In its most basic functionality, the expression parser will only accept as input properly balanced expressions with parentheses in the right places. E.g. "((4 + 5 + 6) * (7 + (5 / 2 / 7)) * 9)". The parser should be able to read expressions in either prefix, infix or postfix notation. E.g. "(+(4,5,6),+(7,/(5,2,7)),9)" for prefix; "((4,5,6)+,(7,(5,2,7)/)+,9)" for postfix. The parser should not be space-sensitive, the presence or absence of spaces, tabs and so on should not make a difference when parsing. Slight variations of the allowed notation could be considered, for example a pre- or postfix notation with spaces instead of commas as separator between arguments. E.g. "(+(4 5 6) +(7 /(5 2 7)) 9)", which incidentally also corresponds to the way of writing expressions in the Schema functional programming language. When implementing this functionality, the "output" of an expression should be consistent with the accepted input. (In other words, any valid string given as input should return an equivalent string after converting it to an Expression and back to a string. Conversely, any string generated as output from an expression should be acceptable as input to the parser without any errors...
  • A more sophisticated functionality should take into account operator precedence to avoid superfluous parentheses. For example, if we know what * and / have precedence over + and -, then we can simplify the expression "((4 + 5 + 6) * (7 + (5 / 2 / 7)) * 9)" to something like "(4+5+ 6)(7 + 5/2/7)*9".

Is your feature request related to a specific need or problem?
Without a proper expression parser, the caclulator is not really practically useful, since creating expressions manually in terms of object trees is very cumbersome, error-prone and time-consuming.

Additional context
Several Java libraries exist for creating parsers, it is recommended to choice the most appropriate one of them rather than to reinvent the wheel from scratch.

Supporting modular arithmetics

Modular arithmetics is like regular integer arithmetics, but restricted to a limited range of positive integer values (e.g. from 0 to 4, considering that all computations are done modulo 4). For more information, see for exemple
- https://brilliant.org/wiki/modular-arithmetic/
- http://www.crypto-it.net/eng/theory/modular-arithmetic.html
Modular arithmetics are for exemple used frequently in cryptography.
(Perhaps, to implement such functionality, we could partly rely on java.Math.BigInteger which provides some support for modular arithmetics.)

[FEATURE] Support for complex numbers

Add support for complex numbers (e.g. 2+5i), expressions based on complex numbers, and arithmetic operations on those complex numbers. Note that a "normal" number should be considered as a special case of a complex numbers. E.g. 5 = 5+0i; 2.7 = 2.7+0i. The use of complex numbers has an effect on how to compute arithmetic operations. E.g. the square root of -1 is undefined for natural or decimal numbers, while it is defined for complex numbers (sqrt(-1)=i since i*i=-1)
When implementing complex numbers, new operations can be added, such as:

  • Computing the modulus (recall that |a+bi| = sqrt(a²+b²)).
  • Converting between cartesian, polar and exponential forms. For instance: sqrt(2) + sqrt(2)i (cartesian) = 2 (cosine(pi/4) + i sine (pi/4)) (polar) = 2 e^(i*pi/4) (exponential).

Be careful of operations that either no longer work, have to be defined in an alternate way, or no longer satisfy the same mathematical properties.

[FEATURE] Supporting rational numbers

Describe the new functionality you would like to see
It would be useful to have primitive built-in support for rational numbers in the calculator (e.g. 3/4, 12/7, ...). A rational number can be seen as a fraction of two integer numbers.
https://en.wikipedia.org/wiki/Rational_number

Is your feature request related to a specific need or problem?
The idea of this extension is NOT to consider such fractions as decimal floating point numbers (e.g. 0.75 instead of 3/4) as this will lead to a loss of precision (e.g. 1/3 = 0.333333... but it is not possible to represent an infinite sequence of numbers in the decimal notation).
So we need arithmetic operations that work directly over rational numbers to avoid such loss of precision.

Additional context
(Some languages, such as Scheme provide built-in support for rational numbers.)

Adding a random number generator

Regardless of the types of numbers allowed by the application, it would be useful to have a random number generator.
If the application supports real numbers, the random generator will provide an arbitrary real number between 0 and 1.
If the application supports integer numbers, then given an integer as input, the random generator will provide a random integer between 0 and the integer provided as input.
(For fractions and complex numbers, to be decided what the random generator should do.)

Adding base conversions

It would be nice to be able to convert numbers between different bases. For instance, 255 in base 10 (decimal) is equal to 11111111 in base 2 (binary) and FF in base 16 (hexadecimal). Ideally, the calculator would be able to handle any base > 1.

This can be extended to rational and even real numbers.

[FEATURE] Time computations

Describe the new functionality you would like to see
It would be nice to be able to compute different time intervals. For instance:

How many hours have elapsed since 18:52?
How long was the interval between may 5, 2020 19:30:32 and march 2, 2020 18:31:19?
Date format is up to the choice of the student, but the ISO format (YYYY-MM-DD) is recommended.
Both the 24-hour and 12-hour time formats need to be taken into account. They can be mixed in requests: e.g. the calculator should be able to answer "03:54 PM - 11:54 = 4 hours".

The application should be able to provide the answer in a unit requested by its user, with the remainder being expressed either fractionally or through sub-units: 2020-05-05 19:30:32 - 2020-03-02 18:31:19 can be expressed as either "64 days, 0 hours, 59 minutes and 13 seconds" or "64.04 days" or "92219 minutes" or "5533153 seconds", ...

Timezones should be taken into account: "05:27 PM CET+0 - 05:27 PM CET+12 = 12 hours".

Subtraction and addition (what day will it be in 173 days?) make sense, multiplication and division do not. Therefore, those operations should not be possible with time computations.

If the user does not specify a start date or time, the current date/time is used. So, a unary request such as "- 18:52" or "+ 00:01" should give the user the time it was 18 hours and 52 minutes ago or the time it'll be in one minute. In this case, the INFIX notation can be considered equivalent to the PREFIX notation.

separation of test code in distinct package(s)

** Issue **

  • In the current version, all production code and test code belong to the same Java package "calculator", even though they are already structured in separate folders (src/main/java/calculator for the production code; and src/test/java/calculator for the test code). It would be more logical to separate all test code in a distinct Java package (without changing the current folder structure).
  • In addition to this, the folder src/test/java/calculator currently contains both the JUnit5 tests as well as helper classes for the Cucumber tests (in particular CalculatorSteps.java and RunCucumberTest.java). It would probably better to separate them into a distance subfolder to make the distinction between unit tests and BDD tests more apparent.

It is likely that the suggested changes require some changes in the test code or production code.

** Classification **
Code restructuring.

Upgrade to Java SE 17 LTS release

** Issue **
Currently, the code builds and compiles with Java 11. The more recent LTS (long-term service) release is Java 17. Hence it would be desirable to upgrade the project to make it work with Java 17.

** Classification **
Upgrade to new version

[Refactor] Move pre-/post-/infix output printing functionality to Visitor design pattern

** Issue **
Currently the functionality of converting an expression to a string using prefix, postfix or infix notation is hardcoded as part of the Expression class hierarchy. More specifically, it is defined in the toString(Notation) method of the Operation class. This does not make much sense, since the way of outputing an expression in string format should be independent of how the expression is structured and represented internally.
A cleaner solution would be to use the Visitor design patterns, that is already present for evaluating expressions. A new visitor could be implemented for outputting arithmetic expressions as strings using different possible notations (prefix, postfix, infix traversal).
At the same time, the "counting methods" to count the numbers and operations and depth of an expression could also be moved out of the expression hierarchy in another visitor.

This refactoring will require to change some of the unit tests as well, since it will change the current way in which the code is structured.

** Classification **
suggested code refactoring

** Related issues **
This proposed refactoring is related to bug issue #39 that will, in principle, be resolved if the proposed refactoring is carried out correctly.

Integrate SonarLint / SonarQube / SonarCloud quality analysis

** Issue **
Run the SonarLint quality analysis (or its cloud-based or CI-based version) for analysis the quality of the code
Add a badge in the README file to report on this quality.
Add CI/CD support (GitHub Actions) to do this upon every new code commit (or pull request?)

** Classification **
quality improvement

[FEATURE] Calculator with memory functionality

Describe the new functionality you would like to see

  • The calculator should allow the user to store in memory specific expressions that he would like to reuse later. The size of the memory to do so can be finite, but should be configurable by the user through some option in the application's interface.
  • The calculater should also be able to log in the calculator's internal memory the history of all expressions that have been previously entered and evaluated. This log should be easily accessible, for example to select and reuse expressions or evaluated results that have been used somewhere in the past.
  • Given the presence of such a history log, it should be possible to have multiple undo/redo functionality. (E.g. the user should be able to go back into the entire history stored in the calculator's memory.)
  • It should be possible to save the history (of all expressions and their results) in a human-readable text file. It should also be possible, when closing the calculator application, to still have access to its recent history when opening the application again (e.g. by saving the history in a file before closing the application, and reading the file when opening the application). It should be possible to open any history file that was previously saved.

[BUG] heterogenous use of in-/post-/prefix notation

Describe the bug
The current implementation has a bug in how to output expression in prefix and postfix notation.

Expected behavior
If one declares a top-level expression to be of prefix notation for example, then the subexpressions may still use a different notation (e.g. prefix or postfix). This does not make much sense. It is the expression as a whole that needs to be printed using a single notation. It should not be the intention to create expressions that contain a mix of different notations such as (( 3 + 4 + 5 ), - ( 5, 4 ), 7) /

Tests needed
Alongside fixing this bug, a test should be added to detect it, as it is not currently caught by the existing tests. More generally speaking, there are currently no tests for composite expressions with a hierarchy depth higher than one. Such tests need to be added as well.

Related issues
This bug issue is related to refactoring issue #41. In principle, if issue number #41 (which is a proposal to refactor the notation code) would be implemented, this particular bug will no longer be present. (But its presence or absence still remains to be tested though...)

Version
This bug has been found in 0.3.1 and all previous releases.

Use JUnit5 for cucumber tests

** Issue **
Currently, the code (see pom.xml file) still relies on the JUnit4 framework to execute the cucumber BDD tests, even though the normal unit tests already use JUnit5. This is for legacy reasons, since at the time the tests were written, Cucumber did not support JUnit5 yet.

** Solution **
Change the pom.xml file, and probably some other configuration files as well, to make Cucumber use the JUnit5 framework instead of JUnit4.

** Classification **
This can be considered as a refactoring / migration to reduce legacy.

[FEATURE] More advanced support for integer arithmetics

  • Better exception handling: The current code is not checking for division by zero exceptions. The current code does not check for exceptions such as too large integers that are not supported by the internal data type (int) used in the MyNumber class. int values are 32 bit in Java, so the values range from -2^31 to 2^31-1. To deal with longer integer values, one could use to “long” type to supports 64 bit integers, i.e., values range from -2^63 to 2^63-1. But an even better alternative would be to use the java.Math.BigInteger class which supports arbitrary-precision integers, and which also provides a set of extra and useful operations that might be useful to support (for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation).
  • It should be possible to represent and manipulate numbers in different bases n (eg. , 2=binary, 8= octal, 16=hexadecimal, and so on...), and to convert numbers between these different bases. Note that, in order to support hexadecimal numbers (especially in combination with a GUI, one also needs to be able to use the A to F characters in the number representation.
    To be discussed whether and how we want to support other bases above 10, and how to represent these numbers. We could easily go up to 36 (since we have 26 letters in the alphabet on top of the 10 digits from 0 to 9. I would not go higher than base 36, since in practice nobody will be using that.
  • Add support for modular arithmetic. Modular arithmetic is for exemple used frequently in cryptography. It is like regular integer arithmetics, but restricted to a limited range of positive integer values. To implement this functionality, it is good to know that java.Math.BigInteger already provides some support for modular arithmetics. Modular numbers allow for new operations, such as the modular multiplicative inverse of a number. Equality checking on modular numbers is also different. For example, under "modulo 5", 4 and 9 should be considered as equal. For more information on modular arithmetic, see for exemple
    https://brilliant.org/wiki/modular-arithmetic/
    and http://www.crypto-it.net/eng/theory/modular-arithmetic.html

[FEATURE] REST API

Describe the new functionality you would like to see
In order to decouple the functionality of the calculator from its user interface (which could be a command-line interface or a graphical user interface) or anything else, it would be useful to offer a simple REST API that allows external clients to access the functionality of the calculator.

Is your feature request related to a specific need or problem?
On the basis of this API, one could for example provide a JavaScript client GUI that communicates with the application to realise its functionality.

Additional context
Many tools, services and frameworks exist to create REST APIs for Java applications.

[BUG] This is a bug

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Describe the steps required to reproduce the problem.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Version
What was the version of the code on which you encountered the problem? If relevant, also provide the specifics of your operating system or other tools and their version that may be important to understand or reproduce the bug.

Additional context
Add any other context about the problem here.

[FEATURE] Adding conversions of measurement units

Describe the new functionality you would like to see
This feature request is a bit unrelated to the other functionalities typically provided by a calculator. The suggestions is to propose functionality to convert values from a given measurement unit to another one.
For example, we would like to convert some length measurement between (centi/deci/...)meters/feet/inches/miles/nautical miles/yards. Similar conversions would be for measurement of areas, currency, power, energy, pressure, speed, temperature, time, volume, weight and masses.

Additional context
I have drawn inspiration from another calculator app to show the idea. Obviously, this functionality can also be implemented in a CLI-version of the calculator application.
Screenshot 2021-01-19 at 15 22 36

[FEATURE] Command-line interface (CLI) and Read-Eval-Print loop (REPL)

Describe the new functionality you would like to see
In order to make the Calculator usable in practice, it is useful to have a command-line interface (CLI) that can be used to type and evaluate arithmetic expression from the console or terminal. To do so, we need support for a a Read-Eval-Print Loop (REPL): when running the application, the user gets a command-line prompt on his console, where he can enter an arbitrary string. This string will be read, parsed and converted into a syntactically valid expression, or a syntax error will be returned if the string does not respect the correct syntax. Valid expressions will be evaluated, and the result of the evaluation will be printed on the console. Then, we can continue with entering a new string to repeat the same process over and over again.

Prerequisite
A prerequisite for realising this feature is the presence of an expression parser, as described in issue #119 .

Incomplete JavaDoc

** Issue **
The JavaDoc is incomplete, many classes and methods have not been documented using JavaDoc.

** Classification **
improvement of documentation

Use GitHub Actions to automating testing, quality analysis and code/test coverage when new commits or pull requests are received

In order to ensure that the code available in this GitHub repository remains of high quality, the workflow should be automated by using GitHub Actions (reusable actions found on the GitHub Marketplace can be used for that purpose https://github.com/marketplace). The current version already contains partial support for some of this, but needs to be improved further.

  • Continuous building and testing: Whenever a new pull request or commit is being made, the unit tests and BDD tests need to be run, and a report should be generated. A pull request cannot be merged and closed as long as there remain failing tests.
  • Continuous coverage and quality analysis: For every new code addition, code/test coverage and code quality checkers should be run and report their results.
  • Continuous reporting: Whenever a new release is published a report needs to be generated and associated as an asset to the release. The report should contain: the full JavaDoc documentation; the full results of the tests having been executed (the release should fail if some tests do not pass); the full results of the code and test coverage analysis; the full results of the quality analysis.
  • The three workflows above should be separated, and latter two workflows should only be run conditional to the success of the first workflow.

[FEATURE] Support for function manipulation

Describe the new functionality you would like to see
This feature request involves storing and manipulating mathematical functions instead of just numerical values. The functions to be stored and manipulated would basically be arithmetic expression containing a single variable x (corresponding to mathematical functions f(x) with 1 argument x). For example, one could represent the following expressions: sin(x), (x^2)+(2*x)+1, (x-1)^2, exp(x^2) assuming that sin, exp, +, - and ^ are predefined functions known to the calculator.
Given such functions one could extend the calculator application to be able to plot/draw such functions on the screen. Optionally, this drawing functionality could be combined with zooming in and out, panning, and so on…
Optionally, in presence of functions, one could implement functionality for computing the derivative and the integral of a given function.

[BUG] integer division by zero

Describe the bug
Division by zero is not supported by the current implementation.

To Reproduce
When compute an arithmetic operation Divides composed of two numbers MyNumber(8) and MyNumber(0),
then computing the value of this number with method computes() returns an
java.lang.ArithmeticException: / by zero

Expected behavior
When trying to divide by a 0 integer, the error should be properly handled (using the Java exception handling mechanism for example), for example to return NaN (or something similar), rather then leading to an exception at runtime.

Tests needed
Unit tests ad BDD tests also need to be added to detect this bug and to ensure that it will not reappear somewhere in the future.

Version
This bug has been reported for version 0.3.1 and all previous versions.

Additional context
When extending the calculator to more general number domains and other arithmetic operations, please be beware of similar restrictions that may apply (in the appropriate number domain), such as logarithms of negative values, which cannot exist in the real number set; but can exist in the complex number set.

Pull up equals() and hashCode() from subclasses of Operation

** Issue **
There is redundant duplicated code in the subclasses of operation. Essentially, the implementation of equals() and hashCode in those subclasses can be moved to the common superclass.

** Classification **
This is a refactoring to reduce code size and code redundancy.

Different number formats and representations

  • Very large or very small decimal numbers should be expressible more compactly using the scientific notation or E-notation. for example, 6.022E23 would be considered as is equivalent to 6.022×10^23, which would be written as 6022 followed by 20 zeroes in "traditional" notation of natural numbers. Similarly, 1.6E-35 would be considered equivalent to 1.6×10^(−35) which would be written as 0.00...00016 (with lots of zeroes after the floating point of the decimal number).
  • It should also be possible to represent and manipulate numbers in different bases n (eg. , 2=binary, 8= octal, 16=hexadecimal, and so on...), and to convert numbers between these different bases. Note that, in order to support hexadecimal numbers (especially in combination with a GUI, one also needs to be able to use the A to F characters in the number representation.
    To be discussed whether and how we want to support other bases above 10, and how to represent these numbers. We could easily go up to 36 (since we have 26 letters in the alphabet on top of the 10 digits from 0 to 9. I would not go higher than base 36, since in practice nobody will be using that.
  • Finally, as supported on most scientific calculators, it should be possible to use and convert numbers from degrees or radians (the use of radians if often more intuitive and useful when working frequently with trigonometric functions like sin, cos, and so on).

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.