├── .env.dist
├── .gitignore
├── LICENSE
├── README.md
├── bin
├── console
└── phpunit
├── composer.json
├── composer.lock
├── config
├── bundles.php
├── packages
│ ├── assets.yaml
│ ├── dev
│ │ ├── debug.yaml
│ │ ├── easy_log_handler.yaml
│ │ ├── monolog.yaml
│ │ ├── routing.yaml
│ │ ├── swiftmailer.yaml
│ │ └── web_profiler.yaml
│ ├── doctrine.yaml
│ ├── doctrine_migrations.yaml
│ ├── framework.yaml
│ ├── prod
│ │ ├── doctrine.yaml
│ │ └── monolog.yaml
│ ├── routing.yaml
│ ├── security.yaml
│ ├── sensio_framework_extra.yaml
│ ├── swiftmailer.yaml
│ ├── test
│ │ ├── framework.yaml
│ │ ├── monolog.yaml
│ │ ├── swiftmailer.yaml
│ │ └── web_profiler.yaml
│ ├── translation.yaml
│ ├── twig.yaml
│ └── validator.yaml
├── routes.yaml
├── routes
│ ├── annotations.yaml
│ └── dev
│ │ ├── twig.yaml
│ │ └── web_profiler.yaml
└── services.yaml
├── package.json
├── phpunit.xml.dist
├── public
├── assets
│ ├── css
│ │ ├── index.css
│ │ └── level.css
│ └── js
│ │ ├── level.js
│ │ └── tablesort.js
├── eula.html
├── index.php
└── res
│ └── level_base.html.twig
├── src
├── Controller
│ ├── .gitignore
│ ├── EditorController.php
│ ├── IndexController.php
│ ├── NazoController.php
│ └── UserController.php
├── Entity
│ ├── .gitignore
│ ├── Level.php
│ └── User.php
├── Kernel.php
└── Repository
│ ├── .gitignore
│ ├── LevelRepository.php
│ └── UserRepository.php
├── symfony.lock
├── templates
├── base.html.twig
├── editor.html.twig
├── index.html.twig
└── levels
│ └── level_base.html.twig
└── webpack.config.js
/.env.dist:
--------------------------------------------------------------------------------
1 | # This file is a "template" of which env vars need to be defined for your application
2 | # Copy this file to .env file for development, create environment variables when deploying to production
3 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
4 |
5 | ###> symfony/framework-bundle ###
6 | APP_ENV=dev
7 | APP_SECRET=a3254a7dabc3c098c4467e895d0d7d7b
8 | #TRUSTED_PROXIES=127.0.0.1,127.0.0.2
9 | #TRUSTED_HOSTS=localhost,example.com
10 | ###< symfony/framework-bundle ###
11 |
12 | ###> doctrine/doctrine-bundle ###
13 | # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
14 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
15 | # Configure your db driver and server_version in config/packages/doctrine.yaml
16 | DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
17 | ###< doctrine/doctrine-bundle ###
18 |
19 | ###> symfony/swiftmailer-bundle ###
20 | # For Gmail as a transport, use: "gmail://username:password@localhost"
21 | # For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
22 | # Delivery is disabled by default via "null://localhost"
23 | MAILER_URL=null://localhost
24 | ###< symfony/swiftmailer-bundle ###
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | ###> symfony/framework-bundle ###
3 | /.env
4 | /public/bundles/
5 | /var/
6 | /vendor/
7 | ###< symfony/framework-bundle ###
8 |
9 | ###> symfony/webpack-encore-pack ###
10 | /node_modules/
11 | /public/build/
12 | npm-debug.log
13 | yarn-error.log
14 | ###< symfony/webpack-encore-pack ###
15 |
16 | ###> symfony/phpunit-bridge ###
17 | .phpunit
18 | /phpunit.xml
19 | ###< symfony/phpunit-bridge ###
20 |
21 | ###> symfony/web-server-bundle ###
22 | /.web-server-pid
23 | ###< symfony/web-server-bundle ###
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Null
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CipherGameFramework
2 | This is the framework that nazo.games uses. It is written in php 7.2 and uses Symfony as its framework.
3 |
4 | It is not recommended to use this framwork directly.
5 | That being said, you have rights to do whatever you want with it
6 | as long as you follow the [LICENSE](https://github.com/harrynull/CipherGameFramework/blob/master/LICENSE).
7 |
8 | ## License
9 |
10 | MIT License
11 |
12 | Copyright (c) 2018 Null
13 |
14 | Permission is hereby granted, free of charge, to any person obtaining a copy
15 | of this software and associated documentation files (the "Software"), to deal
16 | in the Software without restriction, including without limitation the rights
17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 | copies of the Software, and to permit persons to whom the Software is
19 | furnished to do so, subject to the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be included in all
22 | copies or substantial portions of the Software.
23 |
24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 | SOFTWARE.
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | load(__DIR__.'/../.env');
23 | }
24 |
25 | $input = new ArgvInput();
26 | $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true);
27 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env)) && !$input->hasParameterOption('--no-debug', true);
28 |
29 | if ($debug) {
30 | umask(0000);
31 |
32 | if (class_exists(Debug::class)) {
33 | Debug::enable();
34 | }
35 | }
36 |
37 | $kernel = new Kernel($env, $debug);
38 | $application = new Application($kernel);
39 | $application->run($input);
40 |
--------------------------------------------------------------------------------
/bin/phpunit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | ['all' => true],
5 | Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
6 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
7 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
8 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
9 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
10 | Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
11 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
12 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
13 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
14 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
15 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
16 | Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
17 | ];
18 |
--------------------------------------------------------------------------------
/config/packages/assets.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | assets:
3 | json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
4 |
--------------------------------------------------------------------------------
/config/packages/dev/debug.yaml:
--------------------------------------------------------------------------------
1 | debug:
2 | # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
3 | # See the "server:dump" command to start a new server.
4 | dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
5 |
--------------------------------------------------------------------------------
/config/packages/dev/easy_log_handler.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | EasyCorp\EasyLog\EasyLogHandler:
3 | public: false
4 | arguments: ['%kernel.logs_dir%/%kernel.environment%.log']
5 |
6 | #// FIXME: How to add this configuration automatically without messing up with the monolog configuration?
7 | #monolog:
8 | # handlers:
9 | # buffered:
10 | # type: buffer
11 | # handler: easylog
12 | # channels: ['!event']
13 | # level: debug
14 | # easylog:
15 | # type: service
16 | # id: EasyCorp\EasyLog\EasyLogHandler
17 |
--------------------------------------------------------------------------------
/config/packages/dev/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: stream
5 | path: "%kernel.logs_dir%/%kernel.environment%.log"
6 | level: debug
7 | channels: ["!event"]
8 | # uncomment to get logging in your browser
9 | # you may have to allow bigger header sizes in your Web server configuration
10 | #firephp:
11 | # type: firephp
12 | # level: info
13 | #chromephp:
14 | # type: chromephp
15 | # level: info
16 | console:
17 | type: console
18 | process_psr_3_messages: false
19 | channels: ["!event", "!doctrine", "!console"]
20 |
--------------------------------------------------------------------------------
/config/packages/dev/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: true
4 |
--------------------------------------------------------------------------------
/config/packages/dev/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | # See https://symfony.com/doc/current/email/dev_environment.html
2 | swiftmailer:
3 | # send all emails to a specific address
4 | #delivery_addresses: ['me@example.com']
5 |
--------------------------------------------------------------------------------
/config/packages/dev/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: true
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { only_exceptions: false }
7 |
--------------------------------------------------------------------------------
/config/packages/doctrine.yaml:
--------------------------------------------------------------------------------
1 | parameters:
2 | # Adds a fallback DATABASE_URL if the env var is not set.
3 | # This allows you to run cache:warmup even if your
4 | # environment variables are not available yet.
5 | # You should not need to change this value.
6 | env(DATABASE_URL): ''
7 |
8 | doctrine:
9 | dbal:
10 | # configure these for your database server
11 | driver: 'pdo_mysql'
12 | server_version: '5.7'
13 | charset: utf8mb4
14 | default_table_options:
15 | charset: utf8mb4
16 | collate: utf8mb4_unicode_ci
17 |
18 | url: '%env(resolve:DATABASE_URL)%'
19 | orm:
20 | auto_generate_proxy_classes: '%kernel.debug%'
21 | naming_strategy: doctrine.orm.naming_strategy.underscore
22 | auto_mapping: true
23 | mappings:
24 | App:
25 | is_bundle: false
26 | type: annotation
27 | dir: '%kernel.project_dir%/src/Entity'
28 | prefix: 'App\Entity'
29 | alias: App
30 |
--------------------------------------------------------------------------------
/config/packages/doctrine_migrations.yaml:
--------------------------------------------------------------------------------
1 | doctrine_migrations:
2 | dir_name: '%kernel.project_dir%/src/Migrations'
3 | # namespace is arbitrary but should be different from App\Migrations
4 | # as migrations classes should NOT be autoloaded
5 | namespace: DoctrineMigrations
6 |
--------------------------------------------------------------------------------
/config/packages/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | secret: '%env(APP_SECRET)%'
3 | #default_locale: en
4 | #csrf_protection: true
5 | #http_method_override: true
6 |
7 | # Enables session support. Note that the session will ONLY be started if you read or write from it.
8 | # Remove or comment this section to explicitly disable session support.
9 | session:
10 | handler_id: ~
11 |
12 | #esi: true
13 | #fragments: true
14 | php_errors:
15 | log: true
16 |
17 | cache:
18 | # Put the unique name of your app here: the prefix seed
19 | # is used to compute stable namespaces for cache keys.
20 | #prefix_seed: your_vendor_name/app_name
21 |
22 | # The app cache caches to the filesystem by default.
23 | # Other options include:
24 |
25 | # Redis
26 | #app: cache.adapter.redis
27 | #default_redis_provider: redis://localhost
28 |
29 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
30 | #app: cache.adapter.apcu
31 |
--------------------------------------------------------------------------------
/config/packages/prod/doctrine.yaml:
--------------------------------------------------------------------------------
1 | doctrine:
2 | orm:
3 | metadata_cache_driver:
4 | type: service
5 | id: doctrine.system_cache_provider
6 | query_cache_driver:
7 | type: service
8 | id: doctrine.system_cache_provider
9 | result_cache_driver:
10 | type: service
11 | id: doctrine.result_cache_provider
12 |
13 | services:
14 | doctrine.result_cache_provider:
15 | class: Symfony\Component\Cache\DoctrineProvider
16 | public: false
17 | arguments:
18 | - '@doctrine.result_cache_pool'
19 | doctrine.system_cache_provider:
20 | class: Symfony\Component\Cache\DoctrineProvider
21 | public: false
22 | arguments:
23 | - '@doctrine.system_cache_pool'
24 |
25 | framework:
26 | cache:
27 | pools:
28 | doctrine.result_cache_pool:
29 | adapter: cache.app
30 | doctrine.system_cache_pool:
31 | adapter: cache.system
32 |
--------------------------------------------------------------------------------
/config/packages/prod/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: fingers_crossed
5 | action_level: error
6 | handler: nested
7 | excluded_404s:
8 | # regex: exclude all 404 errors from the logs
9 | - ^/
10 | nested:
11 | type: stream
12 | path: "%kernel.logs_dir%/%kernel.environment%.log"
13 | level: debug
14 | console:
15 | type: console
16 | process_psr_3_messages: false
17 | channels: ["!event", "!doctrine"]
18 |
--------------------------------------------------------------------------------
/config/packages/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: ~
4 |
--------------------------------------------------------------------------------
/config/packages/security.yaml:
--------------------------------------------------------------------------------
1 | security:
2 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
3 | providers:
4 | in_memory: { memory: ~ }
5 | firewalls:
6 | dev:
7 | pattern: ^/(_(profiler|wdt)|css|images|js)/
8 | security: false
9 | main:
10 | anonymous: true
11 |
12 | # activate different ways to authenticate
13 |
14 | # http_basic: true
15 | # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
16 |
17 | # form_login: true
18 | # https://symfony.com/doc/current/security/form_login_setup.html
19 |
20 | # Easy way to control access for large sections of your site
21 | # Note: Only the *first* access control that matches will be used
22 | access_control:
23 | # - { path: ^/admin, roles: ROLE_ADMIN }
24 | # - { path: ^/profile, roles: ROLE_USER }
25 |
--------------------------------------------------------------------------------
/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/config/packages/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | url: '%env(MAILER_URL)%'
3 | spool: { type: 'memory' }
4 |
--------------------------------------------------------------------------------
/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/config/packages/test/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: stream
5 | path: "%kernel.logs_dir%/%kernel.environment%.log"
6 | level: debug
7 | channels: ["!event"]
8 |
--------------------------------------------------------------------------------
/config/packages/test/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | disable_delivery: true
3 |
--------------------------------------------------------------------------------
/config/packages/test/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: false
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { collect: false }
7 |
--------------------------------------------------------------------------------
/config/packages/translation.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | default_locale: '%locale%'
3 | translator:
4 | paths:
5 | - '%kernel.project_dir%/translations'
6 | fallbacks:
7 | - '%locale%'
8 |
--------------------------------------------------------------------------------
/config/packages/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | paths: ['%kernel.project_dir%/templates']
3 | debug: '%kernel.debug%'
4 | strict_variables: '%kernel.debug%'
5 |
--------------------------------------------------------------------------------
/config/packages/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | email_validation_mode: html5
4 |
--------------------------------------------------------------------------------
/config/routes.yaml:
--------------------------------------------------------------------------------
1 | #index:
2 | # path: /
3 | # controller: App\Controller\DefaultController::index
4 |
--------------------------------------------------------------------------------
/config/routes/annotations.yaml:
--------------------------------------------------------------------------------
1 | controllers:
2 | resource: ../../src/Controller/
3 | type: annotation
4 |
--------------------------------------------------------------------------------
/config/routes/dev/twig.yaml:
--------------------------------------------------------------------------------
1 | _errors:
2 | resource: '@TwigBundle/Resources/config/routing/errors.xml'
3 | prefix: /_error
4 |
--------------------------------------------------------------------------------
/config/routes/dev/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler_wdt:
2 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
3 | prefix: /_wdt
4 |
5 | web_profiler_profiler:
6 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
7 | prefix: /_profiler
8 |
--------------------------------------------------------------------------------
/config/services.yaml:
--------------------------------------------------------------------------------
1 | # This file is the entry point to configure your own services.
2 | # Files in the packages/ subdirectory configure your dependencies.
3 |
4 | # Put parameters here that don't need to change on each machine where the app is deployed
5 | # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
6 | parameters:
7 | locale: 'en'
8 |
9 | services:
10 | # default configuration for services in *this* file
11 | _defaults:
12 | autowire: true # Automatically injects dependencies in your services.
13 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
14 | public: false # Allows optimizing the container by removing unused services; this also means
15 | # fetching services directly from the container via $container->get() won't work.
16 | # The best practice is to be explicit about your dependencies anyway.
17 |
18 | # makes classes in src/ available to be used as services
19 | # this creates a service per class whose id is the fully-qualified class name
20 | App\:
21 | resource: '../src/*'
22 | exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
23 |
24 | # controllers are imported separately to make sure services can be injected
25 | # as action arguments even if you don't extend any base controller class
26 | App\Controller\:
27 | resource: '../src/Controller'
28 | tags: ['controller.service_arguments']
29 |
30 | # add more service definitions when explicit configuration is needed
31 | # please note that last definitions always *replace* previous ones
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "@symfony/webpack-encore": "^0.19.0",
4 | "webpack-notifier": "^1.6.0"
5 | },
6 | "license": "UNLICENSED",
7 | "private": true,
8 | "scripts": {
9 | "dev-server": "encore dev-server",
10 | "dev": "encore dev",
11 | "watch": "encore dev --watch",
12 | "build": "encore production"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | tests/
23 |
24 |
25 |
26 |
27 |
28 | ./src/
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/public/assets/css/index.css:
--------------------------------------------------------------------------------
1 | .masthead.segment {
2 | min-height: 400px;
3 | padding: 1em 0em;
4 | }
5 |
6 | .masthead h1.ui.header {
7 | margin-top: 1em;
8 | margin-bottom: 0em;
9 | font-size: 4em;
10 | font-weight: normal;
11 | }
12 |
13 | .masthead h2 {
14 | font-size: 1.7em;
15 | font-weight: normal;
16 | }
17 |
18 | .footer.segment {
19 | padding: 5em 0em;
20 | }
21 |
22 | .ui.main.container {
23 | padding: 8em 0em;
24 | }
25 |
26 | .masthead .ui.menu .ui.button {
27 | margin-left: 0.5em;
28 | }
29 |
30 | .right_floated {
31 | float: right;
32 | }
33 |
34 | .tags{
35 | padding: 0 2px;
36 | }
--------------------------------------------------------------------------------
/public/assets/css/level.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #f5f5f5;
3 | }
4 |
5 | body>.grid {
6 | height: 100%;
7 | }
8 |
9 | .column {
10 | max-width: 800px;
11 | }
12 |
13 | .ui.card {
14 | width: 430px;
15 | }
16 |
17 | .ui.input {
18 | width: 90%;
19 | }
20 |
21 | .description {
22 | padding-top: 1rem;
23 | }
--------------------------------------------------------------------------------
/public/assets/js/level.js:
--------------------------------------------------------------------------------
1 | $("#submit").click(function(){
2 | $.ajax({
3 | url: window.location.href+"/submit", type: "POST", data: { answer: $("#answer").val() },
4 | success: function (result) {
5 |
6 | if(!result["success"]){
7 |
8 | $("#message_header").text("未知错误");
9 | $("#message").text("请稍候重试");
10 | $("#incorrect_answer").fadeIn();
11 | setTimeout(function(){$("#incorrect_answer").fadeOut()},5000);
12 | return;
13 | }
14 | if(!result["correct"]){
15 |
16 | $("#message_header").text(result["message_header"]);
17 | $("#message").text(result["message"]);
18 | $("#incorrect_answer").fadeIn();
19 | setTimeout(function(){$("#incorrect_answer").fadeOut()},5000);
20 |
21 | }else{
22 | $('.ui.mini.modal').modal('show'); $('.ui.star.rating').rating();
23 | }
24 | }, error: function (xhr, ajaxOptions, thrownError) {
25 | $("#message_header").text("未知错误");
26 | $("#message").text("请稍候重试");
27 | $("#incorrect_answer").fadeIn();
28 | setTimeout(function(){$("#incorrect_answer").fadeOut()},5000);
29 | }
30 | });
31 | });
32 |
33 | $("#next-level").click(function(){
34 | $.ajax({
35 | url: window.location.href+"/rate", type: "POST",
36 | data: { rating: $('.ui.rating').rating('get rating') },
37 | success: function (result) {
38 | console.log(result);
39 | window.location = window.location.href+"/next"
40 | }
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/public/assets/js/tablesort.js:
--------------------------------------------------------------------------------
1 | /*
2 | A simple, lightweight jQuery plugin for creating sortable tables.
3 | https://github.com/kylefox/jquery-tablesort
4 | Version 0.0.11
5 | */
6 |
7 | (function($) {
8 | $.tablesort = function ($table, settings) {
9 | var self = this;
10 | this.$table = $table;
11 | this.$thead = this.$table.find('thead');
12 | this.settings = $.extend({}, $.tablesort.defaults, settings);
13 | this.$sortCells = this.$thead.length > 0 ? this.$thead.find('th:not(.no-sort)') : this.$table.find('th:not(.no-sort)');
14 | this.$sortCells.on('click.tablesort', function() {
15 | self.sort($(this));
16 | });
17 | this.index = null;
18 | this.$th = null;
19 | this.direction = null;
20 | };
21 |
22 | $.tablesort.prototype = {
23 |
24 | sort: function(th, direction) {
25 | var start = new Date(),
26 | self = this,
27 | table = this.$table,
28 | rowsContainer = table.find('tbody').length > 0 ? table.find('tbody') : table,
29 | rows = rowsContainer.find('tr').has('td, th'),
30 | cells = rows.find(':nth-child(' + (th.index() + 1) + ')').filter('td, th'),
31 | sortBy = th.data().sortBy,
32 | sortedMap = [];
33 |
34 | var unsortedValues = cells.map(function(idx, cell) {
35 | if (sortBy)
36 | return (typeof sortBy === 'function') ? sortBy($(th), $(cell), self) : sortBy;
37 | return ($(this).data().sortValue != null ? $(this).data().sortValue : $(this).text());
38 | });
39 | if (unsortedValues.length === 0) return;
40 |
41 | //click on a different column
42 | if (this.index !== th.index()) {
43 | this.direction = 'asc';
44 | this.index = th.index();
45 | }
46 | else if (direction !== 'asc' && direction !== 'desc')
47 | this.direction = this.direction === 'asc' ? 'desc' : 'asc';
48 | else
49 | this.direction = direction;
50 |
51 | direction = this.direction == 'asc' ? 1 : -1;
52 |
53 | self.$table.trigger('tablesort:start', [self]);
54 | self.log("Sorting by " + this.index + ' ' + this.direction);
55 |
56 | // Try to force a browser redraw
57 | self.$table.css("display");
58 | // Run sorting asynchronously on a timeout to force browser redraw after
59 | // `tablesort:start` callback. Also avoids locking up the browser too much.
60 | setTimeout(function() {
61 | self.$sortCells.removeClass(self.settings.asc + ' ' + self.settings.desc);
62 | for (var i = 0, length = unsortedValues.length; i < length; i++)
63 | {
64 | sortedMap.push({
65 | index: i,
66 | cell: cells[i],
67 | row: rows[i],
68 | value: unsortedValues[i]
69 | });
70 | }
71 |
72 | sortedMap.sort(function(a, b) {
73 | return self.settings.compare(a.value, b.value) * direction;
74 | });
75 |
76 | $.each(sortedMap, function(i, entry) {
77 | rowsContainer.append(entry.row);
78 | });
79 |
80 | th.addClass(self.settings[self.direction]);
81 |
82 | self.log('Sort finished in ' + ((new Date()).getTime() - start.getTime()) + 'ms');
83 | self.$table.trigger('tablesort:complete', [self]);
84 | //Try to force a browser redraw
85 | self.$table.css("display");
86 | }, unsortedValues.length > 2000 ? 200 : 10);
87 | },
88 |
89 | log: function(msg) {
90 | if(($.tablesort.DEBUG || this.settings.debug) && console && console.log) {
91 | console.log('[tablesort] ' + msg);
92 | }
93 | },
94 |
95 | destroy: function() {
96 | this.$sortCells.off('click.tablesort');
97 | this.$table.data('tablesort', null);
98 | return null;
99 | }
100 |
101 | };
102 |
103 | $.tablesort.DEBUG = false;
104 |
105 | $.tablesort.defaults = {
106 | debug: $.tablesort.DEBUG,
107 | asc: 'sorted ascending',
108 | desc: 'sorted descending',
109 | compare: function(a, b) {
110 | if (a > b) {
111 | return 1;
112 | } else if (a < b) {
113 | return -1;
114 | } else {
115 | return 0;
116 | }
117 | }
118 | };
119 |
120 | $.fn.tablesort = function(settings) {
121 | var table, sortable, previous;
122 | return this.each(function() {
123 | table = $(this);
124 | previous = table.data('tablesort');
125 | if(previous) {
126 | previous.destroy();
127 | }
128 | table.data('tablesort', new $.tablesort(table, settings));
129 | });
130 | };
131 |
132 | })(window.Zepto || window.jQuery);
133 |
--------------------------------------------------------------------------------
/public/eula.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Nazo.Games EULA
8 |
9 |
10 |
11 | 最终用户协议
12 | 通过访问和/或使用本网站,即代表您同意接受本协议的所有条件和条款。
13 | 本网站有权随时对本协议进行修改。如果用户选择在本协议变更后继续访问或使用本网站,则视为用户已经接受本协议的修改。
14 | 账户
15 | 本网站有权随时在不通知用户的情况下删除用户账户以节省网站资源。
16 | 本网站有责任使用适当的技术保护您的密码原文的安全(包括但不限于散列函数)。
17 | 隐私
18 | 您允许该网站记录并永久保存您使用的用户名、账户数据(如积分,通关数量)、所用的浏览器、操作系统信息等数据,并将其用于统计、分析或其它用途。
19 | 您允许该网站公开显示您注册时所填写的“显示名”和您的分数,若您没有填写“显示名”,您允许网站使用您邮箱前缀作为“显示名”。
20 | 您允许该网站在某些特定情况下使用您的邮箱对您联络。
21 | 其它
22 | 您同意不对此网站进行攻击,并且您同意承担汇报此网站存在的漏洞的责任。
23 |
24 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | load(__DIR__.'/../.env');
16 | }
17 |
18 | $env = $_SERVER['APP_ENV'] ?? 'dev';
19 | $debug = (bool) ($_SERVER['APP_DEBUG'] ?? ('prod' !== $env));
20 |
21 | if ($debug) {
22 | umask(0000);
23 |
24 | Debug::enable();
25 | }
26 |
27 | if ($trustedProxies = $_SERVER['TRUSTED_PROXIES'] ?? false) {
28 | Request::setTrustedProxies(explode(',', $trustedProxies), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);
29 | }
30 |
31 | if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
32 | Request::setTrustedHosts(explode(',', $trustedHosts));
33 | }
34 |
35 | $kernel = new Kernel($env, $debug);
36 | $request = Request::createFromGlobals();
37 | $response = $kernel->handle($request);
38 | $response->send();
39 | $kernel->terminate($request, $response);
40 |
--------------------------------------------------------------------------------
/public/res/level_base.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 | {% block title %}Level {{level.id}}: {{level.name}}{% endblock %}
3 | {% block stylesheets %}
4 | {{ parent() }}
5 |
6 | {% endblock %}
7 | {% block main %}
8 |
9 |
13 |
14 |
给本关留下一个评价?
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
28 | {% block pre_block %}
29 | {#
30 |
31 |
32 |
33 | #}
34 | {% endblock %}
35 |
36 |
39 |
48 |
49 | {% block description %}
50 | {#
51 |
52 | 下载附件
53 |
54 | #}
55 | {% endblock %}
56 |
57 |
58 |
71 |
72 |
73 |
74 |
75 |
76 | {% endblock %}
77 |
78 | {% block post_body_javascripts %}
79 |
80 | {% endblock %}
81 |
--------------------------------------------------------------------------------
/src/Controller/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harrynull/CipherGameFramework/fab828686dd0825b0cae518544224e4bb62f2d62/src/Controller/.gitignore
--------------------------------------------------------------------------------
/src/Controller/EditorController.php:
--------------------------------------------------------------------------------
1 | cookies->has('user')) return false;
26 | $user = $this->getDoctrine()->getManager()->getRepository(User::class)->find($request->cookies->get('user'));
27 | return $user && $user->getIsAdmin();
28 | }
29 |
30 | private function hasProposePermission(Request $request) : bool {
31 | if (!$request->cookies->has('user')) return false;
32 | $user = $this->getDoctrine()->getManager()->getRepository(User::class)->find($request->cookies->get('user'));
33 | return $user && ($user->getScore() >= 500 || $user->getIsAdmin());
34 | }
35 |
36 | private function editLevel(Level $level, Request $request){
37 | $level->setName($request->request->get('level-name'));
38 | $level->setUnlockScore($request->request->get('unlock-score'));
39 | $level->setScore($request->request->get('score'));
40 | $level->setAuthor($request->request->get('author'));
41 | $level->setAnswer($request->request->get('answer'));
42 | $level->setTags(explode(",", $request->request->get('tags')));
43 | }
44 |
45 | /**
46 | * @Route("/new", methods={"GET"}, name="editor")
47 | */
48 | public function new(Request $request): Response
49 | {
50 | define("DEFAULT_CODE", "{% extends 'levels/level_base.html.twig' %}\n{% block description %}1+1=?{% endblock %}");
51 | return $this->render('editor.html.twig', ["code" => DEFAULT_CODE,
52 | "can_edit" => $this->hasEditPermission($request),
53 | "can_propose" => $this->hasProposePermission($request)]);
54 | }
55 |
56 | /**
57 | * @Route("/new", methods={"POST"})
58 | */
59 | public function submit_new(Request $request): Response
60 | {
61 | if(!$this->hasProposePermission($request))
62 | throw new UnauthorizedHttpException("Permission Denied");
63 | $entityManager = $this->getDoctrine()->getManager();
64 | $level = new Level();
65 | $this->editLevel($level, $request);
66 | $level->setAuthorUser($entityManager->getRepository(User::class)->find($request->cookies->get('user')));
67 | $level->setUnderReview(!$this->hasEditPermission($request));
68 | $entityManager->persist($level);
69 | $entityManager->flush();
70 |
71 | $id = (int)$level->getId();
72 | file_put_contents("../templates/levels/level_{$id}.html.twig", $request->request->get('code'));
73 |
74 | return $this->redirect("/nazo/{$id}");
75 | }
76 | /**
77 | * @Route("/preview", methods={"POST"})
78 | */
79 | public function preview(Request $request): Response
80 | {
81 | if(!$this->hasProposePermission($request))
82 | throw new UnauthorizedHttpException("Permission Denied");
83 | $level = new Level();
84 | $this->editLevel($level, $request);
85 | $level->setUnderReview(true);
86 |
87 | //$twig = new \Twig_Environment(new \Twig_Loader_Array(array()));
88 | $twig = clone $this->container->get('twig');
89 | $template = $twig->createTemplate($request->request->get('code'));
90 | return new Response($template->render(['level'=>$level]));
91 | }
92 |
93 | /**
94 | * @Route("/edit/{id}", methods={"GET"})
95 | */
96 | public function edit(Request $request, Level $level): Response
97 | {
98 | if(!$this->hasEditPermission($request))
99 | throw new UnauthorizedHttpException("Permission Denied");
100 | $id = $level->getId();
101 | $code = file_get_contents("../templates/levels/level_{$id}.html.twig");
102 | return $this->render('editor.html.twig', ["level" => $level, "code" => $code, "can_edit" => true, "can_propose" => true]);
103 | }
104 |
105 | /**
106 | * @Route("/edit/{id}", methods={"POST"})
107 | */
108 | public function submit_edit(Request $request, int $id): Response
109 | {
110 | if(!$this->hasEditPermission($request))
111 | throw new UnauthorizedHttpException("Permission Denied");
112 | $entityManager = $this->getDoctrine()->getManager();
113 | $level = $entityManager->getRepository(Level::class)->find($id);
114 | $this->editLevel($level, $request);
115 | if($level->getUnderReview()){
116 | $level->setUnderReview(false);
117 | $author = $level->getAuthorUser();
118 | $author->setScore($author->getScore()+$level->getScore()*5); // award the author
119 | }
120 | $entityManager->persist($level);
121 | $entityManager->flush();
122 | file_put_contents("../templates/levels/level_{$id}.html.twig", $request->request->get('code'));
123 |
124 | return $this->redirect("/");
125 | }
126 | /**
127 | * @Route("/delete/{id}", methods={"GET"})
128 | */
129 | public function submit_delete(Request $request, int $id): Response
130 | {
131 | if(!$this->hasEditPermission($request))
132 | throw new UnauthorizedHttpException("Permission Denied");
133 | $entityManager = $this->getDoctrine()->getManager();
134 | $level = $entityManager->getRepository(Level::class)->find($id);
135 | $entityManager->remove($level);
136 | $entityManager->flush();
137 | return $this->redirect("/");
138 | }
139 |
140 | /**
141 | * @Route("/setadmin/{user}/{isadmin}", methods={"GET"})
142 | */
143 | public function set_admin_html(Request $request, string $user, bool $isadmin): Response
144 | {
145 | $type = $isadmin?'管理员':'非管理员';
146 | return new Response("将{$user} 设置为{$type} ,确认?".
147 | '');
148 | }
149 |
150 | /**
151 | * @Route("/setadmin/{user}/{isadmin}", methods={"POST"})
152 | */
153 | public function set_admin(Request $request, string $user, bool $isadmin): Response
154 | {
155 | if(hash('sha256', 'somesalt'.$request->request->get('password'))!=='')
156 | return new JsonResponse(array('success' => false, 'reason' => 'incorrect password'));
157 | $entityManager = $this->getDoctrine()->getManager();
158 | $u = $entityManager->getRepository(User::class)->find($user);
159 | if(!$u) return new JsonResponse(array('success' => false, 'reason' => 'incorrect user id'));
160 | $u->setIsAdmin($isadmin);
161 | $entityManager->flush();
162 | return new JsonResponse(array('success' => true));
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/Controller/IndexController.php:
--------------------------------------------------------------------------------
1 | cookies;
28 |
29 | $entityManager = $this->getDoctrine()->getManager();
30 | $user = null;
31 | if ($cookies->has('user')) {
32 | $user = $entityManager->getRepository(User::class)->find($cookies->get('user'));
33 | }
34 |
35 | if ($user == null) { // new user or old uid is invalid
36 | $user = new User();
37 | $entityManager->persist($user);
38 | $entityManager->flush();
39 | }
40 |
41 | $levels = $entityManager->getRepository(Level::class)
42 | ->getAll($request->query->get('review')==1 && $user->getIsAdmin());
43 | $rank = $entityManager->getRepository(User::class)
44 | ->getRank($user->getScore());
45 | $top10 = $entityManager->getRepository(User::class)
46 | ->getTop10Users();
47 |
48 | $response = $this->render('index.html.twig',
49 | ['user' => $user, 'levels' => $levels, 'rank' => $rank, 'top10' => $top10]);
50 | $response->headers->setCookie(new Cookie("user", $user->getId(), time() + (3600 * 24 * 365 * 10)));
51 | return $response;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/Controller/NazoController.php:
--------------------------------------------------------------------------------
1 | getIsAdmin() || $level->getAuthorUser()->getId()===$user->getId();
28 | return ($level->getUnlockScore() <= $user->getScore() || $isException)
29 | && (!$level->getUnderReview() || $isException);
30 | }
31 |
32 | private function getUserFromRequest(Request $request) : User{
33 | return $this->getDoctrine()->getManager()->getRepository(User::class)
34 | ->find($request->cookies->get('user'));
35 | }
36 |
37 | /**
38 | * @Route("/{id}", methods={"GET"}, requirements={"id": "[1-9]\d*"}, name="nazo-levels")
39 | */
40 | public function level(Request $request, int $id): Response
41 | {
42 | $entityManager = $this->getDoctrine()->getManager();
43 | $level_data = $entityManager->getRepository(Level::class)->find($id);
44 | if($level_data == null) throw $this->createNotFoundException('This level does not exist');
45 | $user = $this->getUserFromRequest($request);
46 | if(!$this->permissionCheck($user, $level_data)) return $this->redirect('/');
47 |
48 | if(!in_array($level_data->getId(), $user->getTriedLevels())){
49 | $level_data->setTriedNum($level_data->getTriedNum() + 1);
50 | $tried_levels = $user->getTriedLevels();
51 | $tried_levels[] = $level_data->getId();
52 | $user->setTriedLevels($tried_levels);
53 | $entityManager->flush();
54 | }
55 |
56 |
57 | $response = $this->render("levels/level_{$id}.html.twig", ['level'=>$level_data]);
58 |
59 | return $response;
60 | }
61 | /**
62 | * @Route("/{id}/submit", methods={"POST"}, requirements={"id": "[1-9]\d*"}, name="nazo-levels-submit")
63 | */
64 | public function submit(Request $request, int $id): Response
65 | {
66 | $entityManager = $this->getDoctrine()->getManager();
67 | $level_data = $entityManager->getRepository(Level::class)->find($id);
68 | if($level_data == null) throw $this->createNotFoundException('This level does not exist');
69 | $user = $this->getUserFromRequest($request);
70 |
71 | if(!$this->permissionCheck($user, $level_data))
72 | return new JsonResponse(array('success' => false));
73 |
74 | if($request->request->get('answer') === $level_data->getAnswer()){
75 | if(!in_array($level_data->getId(), $user->getPassedLevels())){
76 | $user->setScore($user->getScore() + $level_data->getScore());
77 | $level_data->setPassedNum($level_data->getPassedNum() + 1);
78 | $passed_levels = $user->getPassedLevels();
79 | $passed_levels[] = $level_data->getId();
80 | $user->setPassedLevels($passed_levels);
81 | }
82 | $entityManager->flush();
83 | return new JsonResponse(array('success' => true, 'correct' => true));
84 | }
85 | else
86 | return new JsonResponse(array('success' => true, 'correct' => false,
87 | "message_header" => "答案不正确", "message" => "再试一次吧"));
88 | }
89 |
90 | /**
91 | * @Route("/{id}/rate", methods={"POST"}, requirements={"id": "[1-9]\d*"})
92 | */
93 | public function rate(Request $request, int $id): Response
94 | {
95 | $entityManager = $this->getDoctrine()->getManager();
96 | $level_data = $entityManager->getRepository(Level::class)->find($id);
97 | if($level_data == null) throw $this->createNotFoundException('This level does not exist');
98 | $user = $this->getUserFromRequest($request);
99 |
100 | if(!$this->permissionCheck($user, $level_data) ||
101 | !in_array($level_data->getId(), $user->getPassedLevels()))
102 | return new JsonResponse(array('success' => false));
103 |
104 | $rating = (int) $request->request->get('rating');
105 | if($rating >= 1 && $rating <=5){
106 | $level_data->setTotalRating($level_data->getTotalRating() + $rating);
107 | $level_data->setRatedNum($level_data->getRatedNum() + 1);
108 | $entityManager->flush();
109 | }
110 |
111 | return new JsonResponse(array('success' => true));
112 | }
113 | /**
114 | * @Route("/{id}/next", methods={"GET"}, requirements={"id": "[1-9]\d*"})
115 | */
116 | public function next(Request $request, int $id): Response
117 | {
118 | $nextid = $id + 1;
119 | $level_data = $this->getDoctrine()->getManager()->getRepository(Level::class)->find($nextid);
120 | $user = $this->getUserFromRequest($request);
121 | if($this->permissionCheck($user, $level_data)) return $this->redirect("/nazo/{$nextid}");
122 | else return $this->redirect("/");
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/src/Controller/UserController.php:
--------------------------------------------------------------------------------
1 | getDoctrine()->getManager();
30 | $email = $request->request->get('email');
31 | $display_name = $request->request->get('display_name');
32 | $password = $request->request->get('password');
33 | $userRepo = $entityManager->getRepository(User::class);
34 |
35 | $new_guid = $request->cookies->get('user');
36 | $user = $userRepo->findByEmail($email);
37 |
38 | if ($user) { // existing user
39 |
40 | if (!password_verify($password, $user->getPassword()))
41 | throw new UnauthorizedHttpException("Incorrect username or password!");
42 | if ($display_name != '') $user->setDisplayName($display_name);
43 | $new_guid = $user->getId();
44 |
45 | } else { // new user
46 |
47 | $user = $userRepo->find($request->cookies->get('user'));
48 | if ($user == null) throw new BadRequestHttpException();
49 | $user->setEmail($email);
50 | $user->setDisplayName( ($display_name!='') ? $display_name : (explode('@', $email)[0]) );
51 | $user->setPassword(password_hash($password, PASSWORD_DEFAULT));
52 |
53 | }
54 | $entityManager->flush();
55 |
56 | $response = $this->redirect("/");
57 | $response->headers->setCookie(new Cookie("user", $new_guid, time() + (3600 * 24 * 365 * 10)));
58 | return $response;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/Entity/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harrynull/CipherGameFramework/fab828686dd0825b0cae518544224e4bb62f2d62/src/Entity/.gitignore
--------------------------------------------------------------------------------
/src/Entity/Level.php:
--------------------------------------------------------------------------------
1 | id;
82 | }
83 |
84 | public function getName(): ?string
85 | {
86 | return $this->name;
87 | }
88 |
89 | public function setName(string $name): self
90 | {
91 | $this->name = $name;
92 |
93 | return $this;
94 | }
95 |
96 | public function getUnlockScore(): ?int
97 | {
98 | return $this->unlock_score;
99 | }
100 |
101 | public function setUnlockScore(int $unlock_score): self
102 | {
103 | $this->unlock_score = $unlock_score;
104 |
105 | return $this;
106 | }
107 |
108 | public function getScore(): ?int
109 | {
110 | return $this->score;
111 | }
112 |
113 | public function setScore(int $score): self
114 | {
115 | $this->score = $score;
116 |
117 | return $this;
118 | }
119 |
120 | public function getTriedNum(): ?int
121 | {
122 | return $this->tried_num;
123 | }
124 |
125 | public function setTriedNum(int $tried_num): self
126 | {
127 | $this->tried_num = $tried_num;
128 |
129 | return $this;
130 | }
131 |
132 | public function getTotalRating(): ?int
133 | {
134 | return $this->total_rating;
135 | }
136 |
137 | public function setTotalRating(int $total_rating): self
138 | {
139 | $this->total_rating = $total_rating;
140 |
141 | return $this;
142 | }
143 |
144 | public function getRatedNum(): ?int
145 | {
146 | return $this->rated_num;
147 | }
148 |
149 | public function setRatedNum(int $rated_num): self
150 | {
151 | $this->rated_num = $rated_num;
152 |
153 | return $this;
154 | }
155 |
156 | public function getPassedNum(): ?int
157 | {
158 | return $this->passed_num;
159 | }
160 |
161 | public function setPassedNum(int $passed_num): self
162 | {
163 | $this->passed_num = $passed_num;
164 |
165 | return $this;
166 | }
167 |
168 | public function getTags(): ?array
169 | {
170 | return $this->tags;
171 | }
172 |
173 | public function setTags(?array $tags): self
174 | {
175 | $this->tags = $tags;
176 |
177 | return $this;
178 | }
179 |
180 | public function getAuthor(): ?string
181 | {
182 | return $this->author;
183 | }
184 |
185 | public function setAuthor(string $author): self
186 | {
187 | $this->author = $author;
188 |
189 | return $this;
190 | }
191 |
192 | public function getAnswer(): ?string
193 | {
194 | return $this->answer;
195 | }
196 |
197 | public function setAnswer(string $answer): self
198 | {
199 | $this->answer = $answer;
200 |
201 | return $this;
202 | }
203 |
204 | public function getUnderReview(): ?bool
205 | {
206 | return $this->under_review;
207 | }
208 |
209 | public function setUnderReview(bool $under_review): self
210 | {
211 | $this->under_review = $under_review;
212 |
213 | return $this;
214 | }
215 |
216 | public function getAuthorUser(): ?User
217 | {
218 | return $this->author_user;
219 | }
220 |
221 | public function setAuthorUser(?User $author_user): self
222 | {
223 | $this->author_user = $author_user;
224 |
225 | return $this;
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/Entity/User.php:
--------------------------------------------------------------------------------
1 | levels = new ArrayCollection();
64 | }
65 |
66 | public function getId(): ?string
67 | {
68 | return $this->id;
69 | }
70 |
71 | public function getPassedLevels(): ?array
72 | {
73 | return $this->passed_levels;
74 | }
75 |
76 | public function setPassedLevels(array $passed_levels): self
77 | {
78 | $this->passed_levels = $passed_levels;
79 |
80 | return $this;
81 | }
82 |
83 | public function getScore(): ?int
84 | {
85 | return $this->score;
86 | }
87 |
88 | public function setScore(int $score): self
89 | {
90 | $this->score = $score;
91 |
92 | return $this;
93 | }
94 |
95 | public function getIsAdmin(): ?bool
96 | {
97 | return $this->is_admin;
98 | }
99 |
100 | public function setIsAdmin(?bool $is_admin): self
101 | {
102 | $this->is_admin = $is_admin;
103 |
104 | return $this;
105 | }
106 |
107 | /**
108 | * @return Collection|Level[]
109 | */
110 | public function getLevels(): Collection
111 | {
112 | return $this->levels;
113 | }
114 |
115 | public function addLevel(Level $level): self
116 | {
117 | if (!$this->levels->contains($level)) {
118 | $this->levels[] = $level;
119 | $level->setAuthorUser($this);
120 | }
121 |
122 | return $this;
123 | }
124 |
125 | public function removeLevel(Level $level): self
126 | {
127 | if ($this->levels->contains($level)) {
128 | $this->levels->removeElement($level);
129 | // set the owning side to null (unless already changed)
130 | if ($level->getAuthorUser() === $this) {
131 | $level->setAuthorUser(null);
132 | }
133 | }
134 |
135 | return $this;
136 | }
137 |
138 | public function getTriedLevels(): array
139 | {
140 | return $this->tried_levels;
141 | }
142 |
143 | public function setTriedLevels(array $tried_levels): self
144 | {
145 | $this->tried_levels = $tried_levels;
146 |
147 | return $this;
148 | }
149 |
150 | public function getEmail(): ?string
151 | {
152 | return $this->email;
153 | }
154 |
155 | public function setEmail(string $email): self
156 | {
157 | $this->email = $email;
158 |
159 | return $this;
160 | }
161 |
162 | public function getPassword(): ?string
163 | {
164 | return $this->password;
165 | }
166 |
167 | public function setPassword(?string $password): self
168 | {
169 | $this->password = $password;
170 |
171 | return $this;
172 | }
173 |
174 | public function getDisplayName(): ?string
175 | {
176 | return $this->display_name;
177 | }
178 |
179 | public function setDisplayName(?string $display_name): self
180 | {
181 | $this->display_name = $display_name;
182 |
183 | return $this;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/src/Kernel.php:
--------------------------------------------------------------------------------
1 | getProjectDir().'/var/cache/'.$this->environment;
21 | }
22 |
23 | public function getLogDir()
24 | {
25 | return $this->getProjectDir().'/var/log';
26 | }
27 |
28 | public function registerBundles()
29 | {
30 | $contents = require $this->getProjectDir().'/config/bundles.php';
31 | foreach ($contents as $class => $envs) {
32 | if (isset($envs['all']) || isset($envs[$this->environment])) {
33 | yield new $class();
34 | }
35 | }
36 | }
37 |
38 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
39 | {
40 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
41 | // Feel free to remove the "container.autowiring.strict_mode" parameter
42 | // if you are using symfony/dependency-injection 4.0+ as it's the default behavior
43 | $container->setParameter('container.autowiring.strict_mode', true);
44 | $container->setParameter('container.dumper.inline_class_loader', true);
45 | $confDir = $this->getProjectDir().'/config';
46 |
47 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
48 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
49 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
50 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
51 | }
52 |
53 | protected function configureRoutes(RouteCollectionBuilder $routes)
54 | {
55 | $confDir = $this->getProjectDir().'/config';
56 |
57 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
58 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
59 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Repository/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/harrynull/CipherGameFramework/fab828686dd0825b0cae518544224e4bb62f2d62/src/Repository/.gitignore
--------------------------------------------------------------------------------
/src/Repository/LevelRepository.php:
--------------------------------------------------------------------------------
1 | createQueryBuilder('u')
25 | ->where('u.under_review = :review')
26 | ->setParameter('review', $underReview)
27 | ->getQuery()
28 | ->getResult();
29 | }
30 | // /**
31 | // * @return Level[] Returns an array of Level objects
32 | // */
33 | /*
34 | public function findByExampleField($value)
35 | {
36 | return $this->createQueryBuilder('l')
37 | ->andWhere('l.exampleField = :val')
38 | ->setParameter('val', $value)
39 | ->orderBy('l.id', 'ASC')
40 | ->setMaxResults(10)
41 | ->getQuery()
42 | ->getResult()
43 | ;
44 | }
45 | */
46 |
47 | /*
48 | public function findOneBySomeField($value): ?Level
49 | {
50 | return $this->createQueryBuilder('l')
51 | ->andWhere('l.exampleField = :val')
52 | ->setParameter('val', $value)
53 | ->getQuery()
54 | ->getOneOrNullResult()
55 | ;
56 | }
57 | */
58 | }
59 |
--------------------------------------------------------------------------------
/src/Repository/UserRepository.php:
--------------------------------------------------------------------------------
1 | getEntityManager()
24 | ->createQuery('
25 | SELECT COUNT(1)
26 | FROM App:User p
27 | WHERE p.score > :score
28 | ')
29 | ->setParameter('score', $score);
30 | return $q->getResult()[0][1]+1;
31 | }
32 |
33 | public function getTop10Users()
34 | {
35 | return $this->createQueryBuilder('u')
36 | ->andWhere('u.display_name is not null')
37 | ->orderBy('u.score', 'DESC')
38 | ->setMaxResults(10)
39 | ->getQuery()
40 | ->getResult();
41 | }
42 | public function findByEmail($value): ?User
43 | {
44 | return $this->createQueryBuilder('u')
45 | ->andWhere('u.email = :val')
46 | ->setParameter('val', $value)
47 | ->getQuery()
48 | ->getOneOrNullResult();
49 | }
50 | // /**
51 | // * @return User[] Returns an array of User objects
52 | // */
53 | /*
54 | public function findByExampleField($value)
55 | {
56 | return $this->createQueryBuilder('p')
57 | ->andWhere('p.exampleField = :val')
58 | ->setParameter('val', $value)
59 | ->orderBy('p.id', 'ASC')
60 | ->setMaxResults(10)
61 | ->getQuery()
62 | ->getResult()
63 | ;
64 | }
65 | */
66 |
67 | /*
68 | public function findOneBySomeField($value): ?User
69 | {
70 | return $this->createQueryBuilder('p')
71 | ->andWhere('p.exampleField = :val')
72 | ->setParameter('val', $value)
73 | ->getQuery()
74 | ->getOneOrNullResult()
75 | ;
76 | }
77 | */
78 | }
79 |
--------------------------------------------------------------------------------
/symfony.lock:
--------------------------------------------------------------------------------
1 | {
2 | "doctrine/annotations": {
3 | "version": "1.0",
4 | "recipe": {
5 | "repo": "github.com/symfony/recipes",
6 | "branch": "master",
7 | "version": "1.0",
8 | "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
9 | }
10 | },
11 | "doctrine/cache": {
12 | "version": "v1.7.1"
13 | },
14 | "doctrine/collections": {
15 | "version": "v1.5.0"
16 | },
17 | "doctrine/common": {
18 | "version": "v2.9.0"
19 | },
20 | "doctrine/dbal": {
21 | "version": "v2.8.0"
22 | },
23 | "doctrine/doctrine-bundle": {
24 | "version": "1.6",
25 | "recipe": {
26 | "repo": "github.com/symfony/recipes",
27 | "branch": "master",
28 | "version": "1.6",
29 | "ref": "ae205d5114e719deb64d2110f56ef910787d1e04"
30 | }
31 | },
32 | "doctrine/doctrine-cache-bundle": {
33 | "version": "1.3.3"
34 | },
35 | "doctrine/doctrine-migrations-bundle": {
36 | "version": "1.2",
37 | "recipe": {
38 | "repo": "github.com/symfony/recipes",
39 | "branch": "master",
40 | "version": "1.2",
41 | "ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1"
42 | }
43 | },
44 | "doctrine/event-manager": {
45 | "version": "v1.0.0"
46 | },
47 | "doctrine/inflector": {
48 | "version": "v1.3.0"
49 | },
50 | "doctrine/instantiator": {
51 | "version": "1.1.0"
52 | },
53 | "doctrine/lexer": {
54 | "version": "v1.0.1"
55 | },
56 | "doctrine/migrations": {
57 | "version": "v1.8.1"
58 | },
59 | "doctrine/orm": {
60 | "version": "v2.6.2"
61 | },
62 | "doctrine/persistence": {
63 | "version": "v1.0.0"
64 | },
65 | "doctrine/reflection": {
66 | "version": "v1.0.0"
67 | },
68 | "easycorp/easy-log-handler": {
69 | "version": "1.0",
70 | "recipe": {
71 | "repo": "github.com/symfony/recipes",
72 | "branch": "master",
73 | "version": "1.0",
74 | "ref": "70062abc2cd58794d2a90274502f81b55cd9951b"
75 | }
76 | },
77 | "egulias/email-validator": {
78 | "version": "2.1.4"
79 | },
80 | "fig/link-util": {
81 | "version": "1.0.0"
82 | },
83 | "jdorn/sql-formatter": {
84 | "version": "v1.2.17"
85 | },
86 | "monolog/monolog": {
87 | "version": "1.23.0"
88 | },
89 | "nikic/php-parser": {
90 | "version": "v4.0.3"
91 | },
92 | "ocramius/proxy-manager": {
93 | "version": "2.1.1"
94 | },
95 | "phpdocumentor/reflection-common": {
96 | "version": "1.0.1"
97 | },
98 | "phpdocumentor/reflection-docblock": {
99 | "version": "4.3.0"
100 | },
101 | "phpdocumentor/type-resolver": {
102 | "version": "0.4.0"
103 | },
104 | "psr/cache": {
105 | "version": "1.0.1"
106 | },
107 | "psr/container": {
108 | "version": "1.0.0"
109 | },
110 | "psr/link": {
111 | "version": "1.0.0"
112 | },
113 | "psr/log": {
114 | "version": "1.0.2"
115 | },
116 | "psr/simple-cache": {
117 | "version": "1.0.1"
118 | },
119 | "sensio/framework-extra-bundle": {
120 | "version": "5.2",
121 | "recipe": {
122 | "repo": "github.com/symfony/recipes",
123 | "branch": "master",
124 | "version": "5.2",
125 | "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
126 | }
127 | },
128 | "swiftmailer/swiftmailer": {
129 | "version": "v6.1.2"
130 | },
131 | "symfony/asset": {
132 | "version": "v4.1.1"
133 | },
134 | "symfony/browser-kit": {
135 | "version": "v4.1.1"
136 | },
137 | "symfony/cache": {
138 | "version": "v4.1.1"
139 | },
140 | "symfony/config": {
141 | "version": "v4.1.1"
142 | },
143 | "symfony/console": {
144 | "version": "3.3",
145 | "recipe": {
146 | "repo": "github.com/symfony/recipes",
147 | "branch": "master",
148 | "version": "3.3",
149 | "ref": "e3868d2f4a5104f19f844fe551099a00c6562527"
150 | }
151 | },
152 | "symfony/css-selector": {
153 | "version": "v4.1.1"
154 | },
155 | "symfony/debug": {
156 | "version": "v4.1.1"
157 | },
158 | "symfony/debug-bundle": {
159 | "version": "4.1",
160 | "recipe": {
161 | "repo": "github.com/symfony/recipes",
162 | "branch": "master",
163 | "version": "4.1",
164 | "ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea"
165 | }
166 | },
167 | "symfony/debug-pack": {
168 | "version": "v1.0.5"
169 | },
170 | "symfony/dependency-injection": {
171 | "version": "v4.1.1"
172 | },
173 | "symfony/doctrine-bridge": {
174 | "version": "v4.1.1"
175 | },
176 | "symfony/dom-crawler": {
177 | "version": "v4.1.1"
178 | },
179 | "symfony/dotenv": {
180 | "version": "v4.1.1"
181 | },
182 | "symfony/event-dispatcher": {
183 | "version": "v4.1.1"
184 | },
185 | "symfony/expression-language": {
186 | "version": "v4.1.1"
187 | },
188 | "symfony/filesystem": {
189 | "version": "v4.1.1"
190 | },
191 | "symfony/finder": {
192 | "version": "v4.1.1"
193 | },
194 | "symfony/flex": {
195 | "version": "1.0",
196 | "recipe": {
197 | "repo": "github.com/symfony/recipes",
198 | "branch": "master",
199 | "version": "1.0",
200 | "ref": "e921bdbfe20cdefa3b82f379d1cd36df1bc8d115"
201 | }
202 | },
203 | "symfony/form": {
204 | "version": "v4.1.1"
205 | },
206 | "symfony/framework-bundle": {
207 | "version": "3.3",
208 | "recipe": {
209 | "repo": "github.com/symfony/recipes",
210 | "branch": "master",
211 | "version": "3.3",
212 | "ref": "87c585d24de9f43bca80ebcfd5cf5cb39445d95f"
213 | }
214 | },
215 | "symfony/http-foundation": {
216 | "version": "v4.1.1"
217 | },
218 | "symfony/http-kernel": {
219 | "version": "v4.1.1"
220 | },
221 | "symfony/inflector": {
222 | "version": "v4.1.1"
223 | },
224 | "symfony/intl": {
225 | "version": "v4.1.1"
226 | },
227 | "symfony/lts": {
228 | "version": "4-dev"
229 | },
230 | "symfony/maker-bundle": {
231 | "version": "1.0",
232 | "recipe": {
233 | "repo": "github.com/symfony/recipes",
234 | "branch": "master",
235 | "version": "1.0",
236 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
237 | }
238 | },
239 | "symfony/monolog-bridge": {
240 | "version": "v4.1.1"
241 | },
242 | "symfony/monolog-bundle": {
243 | "version": "3.1",
244 | "recipe": {
245 | "repo": "github.com/symfony/recipes",
246 | "branch": "master",
247 | "version": "3.1",
248 | "ref": "51b7a31438c8aeeda7931a0ece98a945c91e7f20"
249 | }
250 | },
251 | "symfony/options-resolver": {
252 | "version": "v4.1.1"
253 | },
254 | "symfony/orm-pack": {
255 | "version": "v1.0.5"
256 | },
257 | "symfony/phpunit-bridge": {
258 | "version": "4.1",
259 | "recipe": {
260 | "repo": "github.com/symfony/recipes",
261 | "branch": "master",
262 | "version": "4.1",
263 | "ref": "2955e26d3818b803d82b5de05d91805df5994d3a"
264 | }
265 | },
266 | "symfony/polyfill-ctype": {
267 | "version": "v1.8.0"
268 | },
269 | "symfony/polyfill-intl-icu": {
270 | "version": "v1.8.0"
271 | },
272 | "symfony/polyfill-mbstring": {
273 | "version": "v1.8.0"
274 | },
275 | "symfony/polyfill-php72": {
276 | "version": "v1.8.0"
277 | },
278 | "symfony/process": {
279 | "version": "v4.1.1"
280 | },
281 | "symfony/profiler-pack": {
282 | "version": "v1.0.3"
283 | },
284 | "symfony/property-access": {
285 | "version": "v4.1.1"
286 | },
287 | "symfony/property-info": {
288 | "version": "v4.1.1"
289 | },
290 | "symfony/routing": {
291 | "version": "4.0",
292 | "recipe": {
293 | "repo": "github.com/symfony/recipes",
294 | "branch": "master",
295 | "version": "4.0",
296 | "ref": "cda8b550123383d25827705d05a42acf6819fe4e"
297 | }
298 | },
299 | "symfony/security": {
300 | "version": "v4.1.1"
301 | },
302 | "symfony/security-bundle": {
303 | "version": "3.3",
304 | "recipe": {
305 | "repo": "github.com/symfony/recipes",
306 | "branch": "master",
307 | "version": "3.3",
308 | "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527"
309 | }
310 | },
311 | "symfony/serializer": {
312 | "version": "v4.1.1"
313 | },
314 | "symfony/serializer-pack": {
315 | "version": "v1.0.1"
316 | },
317 | "symfony/stopwatch": {
318 | "version": "v4.1.1"
319 | },
320 | "symfony/swiftmailer-bundle": {
321 | "version": "2.5",
322 | "recipe": {
323 | "repo": "github.com/symfony/recipes",
324 | "branch": "master",
325 | "version": "2.5",
326 | "ref": "3db029c03e452b4a23f7fc45cec7c922c2247eb8"
327 | }
328 | },
329 | "symfony/test-pack": {
330 | "version": "v1.0.2"
331 | },
332 | "symfony/translation": {
333 | "version": "3.3",
334 | "recipe": {
335 | "repo": "github.com/symfony/recipes",
336 | "branch": "master",
337 | "version": "3.3",
338 | "ref": "6bcd6c570c017ea6ae5a7a6a027c929fd3542cd8"
339 | }
340 | },
341 | "symfony/twig-bridge": {
342 | "version": "v4.1.1"
343 | },
344 | "symfony/twig-bundle": {
345 | "version": "3.3",
346 | "recipe": {
347 | "repo": "github.com/symfony/recipes",
348 | "branch": "master",
349 | "version": "3.3",
350 | "ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f"
351 | }
352 | },
353 | "symfony/validator": {
354 | "version": "4.1",
355 | "recipe": {
356 | "repo": "github.com/symfony/recipes",
357 | "branch": "master",
358 | "version": "4.1",
359 | "ref": "0cdc982334f45d554957a6167e030482795bf9d7"
360 | }
361 | },
362 | "symfony/var-dumper": {
363 | "version": "v4.1.1"
364 | },
365 | "symfony/web-link": {
366 | "version": "v4.1.1"
367 | },
368 | "symfony/web-profiler-bundle": {
369 | "version": "3.3",
370 | "recipe": {
371 | "repo": "github.com/symfony/recipes",
372 | "branch": "master",
373 | "version": "3.3",
374 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
375 | }
376 | },
377 | "symfony/web-server-bundle": {
378 | "version": "3.3",
379 | "recipe": {
380 | "repo": "github.com/symfony/recipes",
381 | "branch": "master",
382 | "version": "3.3",
383 | "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
384 | }
385 | },
386 | "symfony/webpack-encore-pack": {
387 | "version": "1.0",
388 | "recipe": {
389 | "repo": "github.com/symfony/recipes",
390 | "branch": "master",
391 | "version": "1.0",
392 | "ref": "b87dfd249390a7b534caa137450277930901236e"
393 | }
394 | },
395 | "symfony/yaml": {
396 | "version": "v4.1.1"
397 | },
398 | "twig/twig": {
399 | "version": "v2.5.0"
400 | },
401 | "webmozart/assert": {
402 | "version": "1.3.0"
403 | },
404 | "zendframework/zend-code": {
405 | "version": "3.3.0"
406 | },
407 | "zendframework/zend-eventmanager": {
408 | "version": "3.2.1"
409 | }
410 | }
411 |
--------------------------------------------------------------------------------
/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {% block title %}謎.Games{% endblock %}
9 |
10 | {% block javascripts %}
11 |
12 |
13 | {% endblock %}
14 | {% block stylesheets %}
15 |
16 | {% endblock %}
17 |
18 |
19 |
20 | {% block header %}{% endblock %}
21 | {% block main %}{% endblock %}
22 | {% block footer %}{% endblock %}
23 | {% block post_body_javascripts %}{% endblock %}
24 | {% block track_code %}
25 |
26 |
27 |
34 |
35 |
36 |
37 | {% endblock %}
38 |
39 |
--------------------------------------------------------------------------------
/templates/editor.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'index.html.twig' %}
2 | {% block stylesheets %}
3 | {{ parent() }}
4 |
10 | {% endblock %}
11 | {% block main %}
12 |
13 |
14 |
15 |
16 |
17 | {% if can_propose == false %}
18 |
19 |
20 |
您需要至少30积分以解锁关卡提交
21 | {% endif %}
22 |
23 |
74 |
75 |
76 | {% endblock %}
77 |
78 | {% block post_body_javascripts %}
79 |
80 |
88 | {% endblock %}
89 |
--------------------------------------------------------------------------------
/templates/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 | {% block stylesheets %}
3 | {{ parent() }}
4 |
5 | {% endblock %}
6 | {% block javascripts %}
7 | {{ parent() }}
8 |
9 | {% endblock %}
10 | {% block header %}
11 |
12 |
13 |
14 |
24 |
25 | 密码
26 |
27 |
28 |
29 |
30 |
31 |
我已阅读并同意本网站的用户协议 。
32 |
33 |
34 | 同步进度
35 |
36 |
37 |
38 |
57 | {% endblock %}
58 |
59 | {% block main %}
60 |
61 |
62 |
63 |
64 |
65 |
73 |
74 |
75 |
{{ user.score }}
76 |
积分
77 |
78 |
79 |
80 |
81 |
{{ rank }}
82 |
排名
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | 关卡
92 | 标题
93 | 作者
94 | 积分
95 | 通过率
96 | 评价
97 |
98 |
99 |
100 | {% for level in levels %}
101 |
102 |
103 | {% if level.id in user.getPassedLevels %} {% endif %}
104 | {% if level.id not in user.getPassedLevels and user.score < level.unlockScore %}
105 |
106 | {% endif %}
107 |
108 | {{level.id}}
109 |
110 | {{level.name}}
111 |
112 | {% if level.underReview %}
113 | (审核)
114 | {% endif %}
115 | {% for tag in level.tags %}
116 | {% if tag!="" %}
117 | {% set tagcolor = tag|split('|') %}
118 |
119 | {{tagcolor[1]}}
120 |
121 | {% endif %}
122 | {% endfor %}
123 |
124 | {{level.author}}
125 | {{level.score}}
126 | {{level.getPassedNum}}/{{level.getTriedNum}}({{(level.getPassedNum/(level.getTriedNum==0?1:level.getTriedNum))*100//1}}%)
127 | {{level.getRatedNum==0? "--": ((level.getTotalRating/level.getRatedNum)|number_format(1)) }}
128 |
129 | {% endfor %}
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | {% for user in top10 %}
138 |
139 | {{ loop.index }}
140 | {{user.getDisplayName}}
141 | {{user.getScore}}
142 |
143 | {% endfor %}
144 |
145 |
146 |
147 |
148 |
149 |
150 | {% endblock %}
151 |
152 | {% block footer %}
153 |
170 | {% endblock %}
171 |
172 | {% block post_body_javascripts %}
173 |
190 |
191 | {% endblock %}
192 |
--------------------------------------------------------------------------------
/templates/levels/level_base.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 | {% block title %}Level {{level.id}}: {{level.name}}{% endblock %}
3 | {% block stylesheets %}
4 | {{ parent() }}
5 |
6 | {% endblock %}
7 | {% block main %}
8 |
9 |
13 |
14 |
给本关留下一个评价?
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 | {% if level.underReview %}
28 |
29 |
30 |
31 |
您所查看的关卡正在审核中
32 | {% endif %}
33 |
34 | {% block pre_block %}
35 | {#
36 |
37 |
38 |
39 | #}
40 | {% endblock %}
41 |
42 |
45 |
56 |
57 |
58 | {% block description %}
59 | {#
60 |
61 | 下载附件
62 |
63 | #}
64 | {% endblock %}
65 |
66 |
67 |
80 |
81 |
82 |
83 |
84 |
85 | {% endblock %}
86 |
87 | {% block post_body_javascripts %}
88 |
89 | {% endblock %}
90 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var Encore = require('@symfony/webpack-encore');
2 |
3 | Encore
4 | // directory where compiled assets will be stored
5 | .setOutputPath('public/build/')
6 | // public path used by the web server to access the output path
7 | .setPublicPath('/build')
8 | // only needed for CDN's or sub-directory deploy
9 | //.setManifestKeyPrefix('build/')
10 |
11 | /*
12 | * ENTRY CONFIG
13 | *
14 | * Add 1 entry for each "page" of your app
15 | * (including one that's included on every page - e.g. "app")
16 | *
17 | * Each entry will result in one JavaScript file (e.g. app.js)
18 | * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
19 | */
20 | .addEntry('app', './assets/js/app.js')
21 | //.addEntry('page1', './assets/js/page1.js')
22 | //.addEntry('page2', './assets/js/page2.js')
23 |
24 | /*
25 | * FEATURE CONFIG
26 | *
27 | * Enable & configure other features below. For a full
28 | * list of features, see:
29 | * https://symfony.com/doc/current/frontend.html#adding-more-features
30 | */
31 | .cleanupOutputBeforeBuild()
32 | .enableBuildNotifications()
33 | .enableSourceMaps(!Encore.isProduction())
34 | // enables hashed filenames (e.g. app.abc123.css)
35 | .enableVersioning(Encore.isProduction())
36 |
37 | // enables Sass/SCSS support
38 | //.enableSassLoader()
39 |
40 | // uncomment if you use TypeScript
41 | //.enableTypeScriptLoader()
42 |
43 | // uncomment if you're having problems with a jQuery plugin
44 | //.autoProvidejQuery()
45 | ;
46 |
47 | module.exports = Encore.getWebpackConfig();
48 |
--------------------------------------------------------------------------------