Coder Social home page Coder Social logo

naturalsolutions / ecosecrets Goto Github PK

View Code? Open in Web Editor NEW
14.0 9.0 6.0 11.95 MB

ecoSecrets is a web application which enables users to manage their camera traps data

Home Page: https://demo.ecosecrets.natural-solutions.eu/

License: GNU General Public License v3.0

Shell 0.45% Dockerfile 0.67% Python 24.00% HTML 0.50% CSS 0.97% TypeScript 69.61% Mako 0.13% JavaScript 0.34% FreeMarker 3.34%
camera-traps wildlife biodiversity python react data picture opensource

ecosecrets's Introduction

ecoSecrets - a web application enabling users to manage their camera traps data

ecoSecrets is an open-source web application that aims to facilitate biodiversity studies that use autonomous data collection devices such as camera traps. This web-application is in development and offers several features that meet the needs of biodiversity stakeholders:

  • project management: to delimit the studies according to their context
  • management of study sites: to identify spatial scope
  • device management: to specify technical characteristics of the tools used in the field and their availability
  • deployment management: to characterize spatio-temporal limits of data acquisition
  • media management: to standardize and optimize the storage of collected data
  • media processing: to enable the addition of annotations to the raw data

We would be delighted if you use it, or even contribute in its development.

A demo is available here. Don't hesitate to try it out! User : admin ; password : password


Documentation (in french for now): ecoSecrets documentation



Installation

Prerequisite

Docker and docker-compose must be installed on the server/machine (cf. official website).

Application downloading

Replace the X.Y.Z mention by the name of the release you want to install.

cd
wget https://github.com/naturalsolutions/ecosecrets/archive/refs/tags/X.Y.Z.zip
unzip X.Y.Z.zip
rm X.Y.Z.zip
mv ecosecrets-X.Y.Z ecosecrets/

Settings

Copy the .env.sample inside the docker directory to .env:

cd ecosecrets
cp docker/.env.sample docker/.env
nano docker/.env

Edit freely this .env file to change credentials for instance. Here are the main parameters you usually want to modify:

  • ENV : uncomment it to activate the production mode (only if your app has been configured with a domain name)
  • DOMAIN : localhost, an IP address or a domain name (according to your context)
  • PROTOCOL : modify it to "https" if you want to activate HTTPS
  • HTTP_HTTPS_PORT : usually 80 for HTTP protocol and 443 for HTTPS
  • DB_USER : the name you want for the DB user
  • DB_PASSWORD : the password you want for the DB user
  • DB_NAME : the name you want for the DB
  • MINIO_ROOT_USER : the name you want for the Minio user
  • MINIO_ROOT_PASSWORD : the password you want for the Minio user

In the current version (0.1.1), you can't modify the APP_USER and the APP_PASSWORD directly in this file. You will be able to modify the admin password trough Keycloak later on.

Launching

./scripts/docker.sh up -d

With the default settings, the app will run on http://localhost:8889/ but the port of each service will be avaible to debug. This URL must be adapted to your context (depending on chosen protocol, domain and port).

Sample data (for testing only)

Sample data can be generated by using the following command:

./scripts/docker.sh exec api python -c "from src.connectors.database import init_db; init_db()"

Authentication

ecoSecrets uses Keycloak version 21.1.0 as authentication system.

A keycloak service is provided in the docker-compose.yml file. This also sets up the keycloak instance to create a new realm, add clients (frontend and backend) and create an admin user (credentials: admin / password).

For now, there is no right implemented in the app. This means that all users have the same rights in ecoSecrets. The admin user created above can log into the app and manage users via the administration console of keycloak (http://localhost:8889/auth by default).

You can use your own keycloak instance if you wish, just change in the .env the keycloak env variables. Be careful, all versions of keycloak may not be supported.

Development

Launch backend tests

Tests are written with pytest and can be launched with the following command:

./scripts/docker.sh exec api pytest tests --cov-report html:/home/app/src/htmlcov --cov=src

The default config assumes that the backend is accessing the database through the docker network (via "db" adress) which prevents backend tests from being run locally (outside a container).

API/backend documentation

The openapi documentation accessible via swagger is available here:

http://localhost:8889/api/v1/docs

ecoSecrets app documentation (in french for now)

The documentation is generated with mkdocs and is exposed on port 8133 to be able to work on it with automatic reloading.

http://localhost:8133

Contributing

To contribute to this project, please fork and create a pull request, describing the new functionality or bug fixed. Please link to an issue if relevant. We use 'black' and 'isort' for Python code-formatting, this is checked via a GitHub action.

Licence

ecoSecrets
Copyright (C) 2023 Natural Solutions

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

ecosecrets's People

Contributors

julien-gr4z avatar mathildens avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ecosecrets's Issues

Analyse de données / distance sampling

Il serait intéressant de regarder comment intégrer ce type d'outil a ecoSecret pour traiter les données récoltée:

The Distance project provides software for the design and analysis of distance sampling surveys of wildlife populations. This software takes two forms: a Windows-based program and a suite of packages for the statistical programming language R.

https://distancesampling.org/
https://besjournals.onlinelibrary.wiley.com/doi/full/10.1111/2041-210X.12790

[Bug] Annotation form

Si une observation est créée sans être enregistrée et que l'on passe à la photo suivante, alors le formulaire d'annotation ne fonctionne plus correctement.


The annotation form no longer works when moving on to the next photo if an observation has been created but not saved.

[Bug] Formulaire de déploiement / Deployment form

[English below]
Dans le formulaire de déploiement, les champs concernant les modes de déclenchement (automatique/détection) présentent plusieurs anomalies :

  • les valeurs associées ne sont pas enregistrées lors de la création d'un déploiement,
  • les champs présentent des comportements anormaux,
  • l'affichage n'est pas homogène par rapport aux autres champs.

In the deployment form, the fields about modes (automatic/detection) show several issues:

  • values are not saved when creating a deployment,
  • fields may have wrong behaviors,
  • display is not homogeneous compared to the other fields.

Sound samples

Would ecoSecret be able to manage sound samples in the future?

Capture / Recapture (ReID)

Il serait intéressant de faire une étude sur les espèces sur lesquelles c'est envisageable :

La réidentification (re-ID) des individus animaux constitue un défi de longue date pour la recherche en écologie. Des techniques telles que le marquage, la cicatrisation, le cerclage et les analyses ADN des follicules pileux ou des selles sont précis mais coûteux, intrusif pour l'animal et laborieux pour l'équipe de recherche sur le terrain. Alternativement, la réidentification peut être effectuée par identification visuelle basée sur des marques naturelles, par exemple sur des images de pièges photographiques.

https://www.natural-solutions.eu/blog/identification-individuelle-reid
https://static1.squarespace.com/static/519a7bc0e4b08ccdf8f31445/t/62c688b900b4ed77e4e3861c/1657178314454/Rapport_Stage_leger.pdf

Problème installation v0.1.0

Bonjour,

Je rencontre un problème d'installation avec la nouvelle version de GeoCam. Voici le message d'erreur que je reçois lors de l'exécution de la commande ./scripts/docker.sh up -d :

 ✔ Container geonature-annotation-doc-1       Running                                                                               0.0s 
 ✔ Container geonature-annotation-taxapi-1    Started                                                                              23.4s 
 ✘ Container geonature-annotation-minio-1     Error                                                                                11.5s 
 ✔ Container geonature-annotation-db-1        Healthy                                                                              13.6s 
 ✘ Container geonature-annotation-keycloak-1  Error                                                                                 4.9s 
 ✔ Container geonature-annotation-api-1       Recreated                                                                             7.2s 
 ✔ Container geonature-annotation-frontend-1  Recreated                                                                             3.9s 
 ✔ Container geonature-annotation-traefik-1   Recreated                                                                             2.9s 

Je n'ai rien trouvé de particulier dans dans la partie "minio". Par contre, quand je lance la commande ./scripts/docker.sh logs keycloak, j'ai ce message d'erreur qui s'affiche :

keycloak-1  | 2023-11-28 10:27:18,183 INFO  [org.infinispan.SERVER] (keycloak-cache-init) ISPN005054: Native IOUring transport not available, using NIO instead: io.netty.incubator.channel.uring.IOUring
keycloak-1  | 2023-11-28 10:27:18,290 WARN  [io.quarkus.vertx.http.runtime.VertxHttpRecorder] (main) The X-Forwarded-* and Forwarded headers will be considered when determining the proxy address. This configuration can cause a security issue as clients can forge requests and send a forwarded header that is not overwritten by the proxy. Please consider use one of these headers just to forward the proxy address in requests.
keycloak-1  | 2023-11-28 10:27:18,299 WARN  [io.agroal.pool] (agroal-11) Datasource '<default>': Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
keycloak-1  | 2023-11-28 10:27:18,349 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
keycloak-1  | 2023-11-28 10:27:18,370 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
keycloak-1  | 2023-11-28 10:27:18,387 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
keycloak-1  | 2023-11-28 10:27:19,306 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (development) mode
keycloak-1  | 2023-11-28 10:27:19,306 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to obtain JDBC connection
keycloak-1  | 2023-11-28 10:27:19,307 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
keycloak-1  | 2023-11-28 10:27:19,307 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Connection refused
keycloak-1  | 2023-11-28 10:27:19,307 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '--verbose' option. Also you can use '--help' to see the details about the usage of the particular command.

En général, je règle ce genre de souci via le fichier pg_hba.conf, mais là, je n'ai pas de dossier /etc/postgres dans ma VM. La BDD doit sûrement s'installer ailleurs (via Alembic peut-être ?). A moins que mon souci ne provienne d'un simple paramètre mal renseigné dans le fichier .env ? J'ai indiqué une adresse du type "192.168.x.x" pour ${DOMAIN} et "localhost" pour ${DB_ADDR}. Le port de la BDD n'est pas demandé et celui que j'ai indiqué pour ${HTTP_HTTPS_PORT} est le "8889".

Une idée pour résoudre ce problème ?

[Feature] Prise en charge des médias vidéos

Dans le cadre d'une prestation pour le Parc Naturel régional de Millevaches en Limousin, l'implémentation de la gestion et du traitement des médias vidéo est mise en place.

L'objectif est de permettre à un utilisateur d'importer des vidéos et de les visualiser dans l'interface web afin de les annoter.

Actuellement, le format vidéo n'est pas géré. Il est nécessaire de modifier la gestion du stockage des médias et l'affichage sur les différentes pages de l'application.

Les développements suivants sont donc nécessaires pour mettre en place les fonctionnalités suivantes :

  1. Import des médias vidéo :
  • Modification de l'API
  • Modification du service backend pour l'import de médias : Détection automatisée du type de fichier basé sur le type MIME
  1. Affichage de la miniature :
  • Modification du code frontend pour afficher le média dans la galerie de déploiement
  1. Annotation de la vidéo :
  • Modification du code frontend pour ajouter un lecteur vidéo sur la page d'annotation
  • Modification du code frontend pour permettre une navigation fluide lors du passage d'une vidéo à une autre

[Feature] User documentation

Many users of the demo stopped at the creation of a project. Potentially because of the difficulty of using the tool for the first time.
Indeed, it is necessary to create objects and to understand the functioning and structure of GeoCam to use it.

This is why a short user documentation (which will be improved) has been published to help you understand how GeoCam works. It is available here: https://natural-solutions.gitlab.io/geonature/annotation/user/start/

We will also put a button in the header of the tool to access it easily from the tool itself.

Gamifiication

Il serait intéressant de jouer sur l'appétence au jeux des utilisateurs.

https://www.natural-solutions.eu/blog/gamification

Pour une expérience réussie, il faut s'intéresser aux joueurs.

Certaines personnes sont plus ou moins sensibles aux éléments de l'activité gamifiée.

« les Killers » sont motivés par l'envie de gagner, la rivalité, la compétition
« les Pro-sociaux » sont motivés par le sentiment de l'appartenance à une communauté, un réseau
« les Collectionneurs » sont motivés par l’atteinte d’un statut, la réalisation d’objectifs
« les Explorateurs » sont motivés par l'exploration de l’univers et la découverte de l’environnement

[Feature] Gestion de 2 fichiers par observation pour gestion des données audio par geocam

Idée: si Geocam pouvait gérer pour chaque 'observation' 2 fichiers, 1 fichier image + un autre d'un autre format, alors l'outil pourrait être utile pour la gestion et annotation de fichier audio: l'image affichée
serait celle du spectrogramme correspondant au fichier audio, le fichier audio lui-même étant
accessible par un bouton pour écoute/téléchargement etc. Le spectro pourrait d'ailleurs être créé 'in situ' par geocam au moment de l'upload d'un fichier reconnu comme un fichier audio, ou bien créé par ailleurs par l'utilisateur et chargé comme une image de piège photo.
L'avantage que je vois à cela c'est que toute la structure mise en place pour passer un modèle d'IA sur les images de pièges photo est alors réutilisable pour des modèles d'IA audio, la grande majorité étant basée sur les
images des spectros.

[Feature] Do not reload page when clicking on breadcrumb

Clicking on a breadcrumb element leads to a page reload which is not wanted.

This piece of code should help preventing this reload :

import { Link as ReactLink} from 'react-router-dom'
// add component and replace href with to
<Link
  component={ReactLink}
  underline={props.isActive ? "none" : "hover"}
  color={props.isActive ? "#00000" : "#2fa37c"}
  to={props.isActive ? "" : props.link}
  variant="body2"
>

Careful: Need to check if all the api calls are done like if the page is reloaded and if the breadcrumb is robust with this "new" link

Problème d'installation

Bonjour,

J'essaye d'installer GeoCam sur un serveur Debian 11. Je ne suis pas familier de Docker, il doit y avoir quelque chose que je n'ai pas compris.

Voici ce que j'ai fait jusqu'à présent :

  • récupéré la version dev de GeoCam présent sur le dépôt
  • installé docker via : sudo apt install docker
  • installé la dernière version de docker-compose via : sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose, puis sudo chmod +x /usr/local/bin/docker-compose
  • modifié légèrement le fichier docker/.env, puis exécuté la commande ./scripts/docker.sh up -d comme indiqué dans la documentation

Lors de l'exécution de ce dernier script, une seule erreur apparaît :

✔ Network geonature-annotation_annotation_nw  Created                                                                       0.3s 
 ✔ Network geonature-annotation_default        Created                                                                       0.2s 
 ✔ Volume "geonature-annotation_db_data"       Created                                                                       0.1s 
 ✔ Volume "geonature-annotation_minio_data"    Created                                                                       0.0s 
 ✔ Container geonature-annotation-keycloak-1   Started                                                                       7.2s 
 ✔ Container geonature-annotation-minio-1      Healthy                                                                      38.2s 
 ✔ Container geonature-annotation-db-1         Healthy                                                                      27.7s 
 ✔ Container geonature-annotation-doc-1        Started                                                                       7.2s 
 ✔ Container geonature-annotation-api-1        Healthy                                                                      60.3s 
 ✘ Container geonature-annotation-frontend-1   Error                                                                        69.5s 
 ✔ Container geonature-annotation-traefik-1    Created 

@mvergez, as-tu une piste pour m'aiguiller s'il te plaît ? Peut-être ai-je oublié d'installer quelque chose ou peut-être que je n'ai pas renseigné correctement un paramètre dans le fichier docker/.env ?

Problème test installation

Bonjour,

Par curiosité, je voulais me lancer dans une première installation de GeoCam sur une VM locale (ubuntu server 22.04).
Je rencontre cependant une erreur au moment d'execution de ./scripts/docker.sh up -d

$ sudo ./scripts/docker.sh up -d
[+] Running 7/7
 ✔ Container geonature-annotation-minio-1     Healthy                                                0.4s 
 ✔ Container geonature-annotation-db-1        Healthy                                                0.3s 
 ✔ Container geonature-annotation-doc-1       Running                                                0.0s 
 ✔ Container geonature-annotation-keycloak-1  Healthy                                                0.4s 
 ✘ Container geonature-annotation-api-1       Error                                                  0.2s 
 ✔ Container geonature-annotation-frontend-1  Recreat...                                             0.0s 
 ✔ Container geonature-annotation-traefik-1   Recreate...                                            0.0s 
dependency failed to start: container geonature-annotation-api-1 is unhealthy

Et voici ce que me donne les logs

$ sudo docker logs geonature-annotation-api-1
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO:     Will watch for changes in these directories: ['/home/app']
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [1] using StatReload
Process SpawnProcess-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/usr/local/lib/python3.8/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/.venv/lib/python3.8/site-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
    target(sockets=sockets)
  File "/.venv/lib/python3.8/site-packages/uvicorn/server.py", line 61, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/usr/local/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/.venv/lib/python3.8/site-packages/uvicorn/server.py", line 68, in serve
    config.load()
  File "/.venv/lib/python3.8/site-packages/uvicorn/config.py", line 467, in load
    self.loaded_app = import_from_string(self.app)
  File "/.venv/lib/python3.8/site-packages/uvicorn/importer.py", line 21, in import_from_string
    module = importlib.import_module(module_str)
  File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 843, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/app/src/main.py", line 6, in <module>
    from src.keycloak.idp import idp
  File "/home/app/src/keycloak/idp.py", line 4, in <module>
    idp = Keycloak(
  File "/home/app/src/keycloak/base.py", line 10, in __init__
    super().__init__(**kwargs)
  File "/.venv/lib/python3.8/site-packages/fastapi_keycloak/api.py", line 162, in __init__
    self._get_admin_token()  # Requests an admin access token on startup
  File "/.venv/lib/python3.8/site-packages/fastapi_keycloak/api.py", line 346, in _get_admin_token
    response = requests.post(url=self.token_uri, headers=headers, data=data, timeout=self.timeout)
  File "/.venv/lib/python3.8/site-packages/requests/api.py", line 115, in post
    return request("post", url, data=data, json=json, **kwargs)
  File "/.venv/lib/python3.8/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/.venv/lib/python3.8/site-packages/requests/sessions.py", line 575, in request
    prep = self.prepare_request(req)
  File "/.venv/lib/python3.8/site-packages/requests/sessions.py", line 486, in prepare_request
    p.prepare(
  File "/.venv/lib/python3.8/site-packages/requests/models.py", line 368, in prepare
    self.prepare_url(url, params)
  File "/.venv/lib/python3.8/site-packages/requests/models.py", line 439, in prepare_url
    raise MissingSchema(
requests.exceptions.MissingSchema: Invalid URL 'None': No scheme supplied. Perhaps you meant https://None?

Pour info, je n'ai modifié que les paramètres suivants dans le .env:

N'hésitez pas si besoin d'éléments complémentaires.
En vous remerciant par avance.

[Feature] Media preprocessing by recognition algorithms (DeepFaune)

[English below]

Une fois importés, les médias peuvent être annotés manuellement via la page d’annotation. Cette étape est un goulot d’étranglement dans l’analyse des données. Un pré-traitement des données générant automatiquement des annotations pourrait faciliter et accélérer cette étape.

En effet, les annotations (e.g., taxonomiques, individuelles) peuvent être prédites par un algorithme de reconnaissance. Concernant les annotations taxonomiques, Deep Faune est un bon candidat car il est performant pour catégoriser la faune française en grands groupes (Rigoudy et al., 2022). Il parait donc pertinent pour de nombreux utilisateurs français qui pourraient bénéficier de son intégration.

Il parait indispensable que les valeurs prédites puissent être confirmées ou corrigées afin que les données associées aux images soient de bonne qualité. Les valeurs prédites pourraient par exemple dans un premier temps être affichées dans un encart sur la page d’annotation, puis par la suite directement générer un pré-remplissage du formulaire d’annotation.

Il faudra également définir la gestion du déclenchement du pré-traitement d’annotation automatisé (e.g., sur demande l’utilisateur ou automatiquement lors de l’import).


When imported, the media can be manually annotated. To facilitate and speed up this step, it would be interesting to implement an automated preprocessing of the data.

A recognition algorithm could predict taxonomic annotations. For instance, Deep Faune well perfoms in predicting French fauna into large taxonomic groups (Rigoudy et al., 2022). It seems to be relevant for the users' needs and could be integrated.

The predicted values would be displayed to the user who could confirm or correct it, in order to insure high annotation quality. To implement this quickly, in a first time, it could be displayed in a separate insert. Then, the annotation form could be pre-filled with the predited values.

A question still remains about the preprocessing launch (e.g., on user request or automatically when data are imported?).

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.