text:
<?php
/**
 * Post Types
 *
 * Registers post types and taxonomies
 *
 * @class       WC_Post_types
 * @version     2.3.0
 * @package     WooCommerce/Classes/Products
 * @category    Class
 * @author      WooThemes
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC_Post_types Class
 */
class WC_Post_types {

	/**
	 * Hook in methods.
	 */
	public static function init() {
		add_action( 'init', array( __CLASS__, 'register_taxonomies' ), 5 );
		add_action( 'init', array( __CLASS__, 'register_post_types' ), 5 );
		add_action( 'init', array( __CLASS__, 'register_post_status' ), 9 );
		add_action( 'init', array( __CLASS__, 'support_jetpack_omnisearch' ) );
		add_filter( 'rest_api_allowed_post_types', array( __CLASS__, 'rest_api_allowed_post_types' ) );
	}

	/**
	 * Register core taxonomies.
	 */
	public static function register_taxonomies() {
		if ( taxonomy_exists( 'product_type' ) ) {
			return;
		}

		do_action( 'woocommerce_register_taxonomy' );

		$permalinks = get_option( 'woocommerce_permalinks' );

		register_taxonomy( 'product_type',
			apply_filters( 'woocommerce_taxonomy_objects_product_type', array( 'product' ) ),
			apply_filters( 'woocommerce_taxonomy_args_product_type', array(
				'hierarchical'      => false,
				'show_ui'           => false,
				'show_in_nav_menus' => false,
				'query_var'         => is_admin(),
				'rewrite'           => false,
				'public'            => false
			) )
		);

		register_taxonomy( 'product_cat',
			apply_filters( 'woocommerce_taxonomy_objects_product_cat', array( 'product' ) ),
			apply_filters( 'woocommerce_taxonomy_args_product_cat', array(
				'hierarchical'          => true,
				'update_count_callback' => '_wc_term_recount',
				'label'                 => __( 'Product Categories', 'woocommerce' ),
				'labels' => array(
						'name'              => __( 'Product Categories', 'woocommerce' ),
						'singular_name'     => __( 'Product Category', 'woocommerce' ),
						'menu_name'         => _x( 'Categories', 'Admin menu name', 'woocommerce' ),
						'search_items'      => __( 'Search Product Categories', 'woocommerce' ),
						'all_items'         => __( 'All Product Categories', 'woocommerce' ),
						'parent_item'       => __( 'Parent Product Category', 'woocommerce' ),
						'parent_item_colon' => __( 'Parent Product Category:', 'woocommerce' ),
						'edit_item'         => __( 'Edit Product Category', 'woocommerce' ),
						'update_item'       => __( 'Update Product Category', 'woocommerce' ),
						'add_new_item'      => __( 'Add New Product Category', 'woocommerce' ),
						'new_item_name'     => __( 'New Product Category Name', 'woocommerce' )
					),
				'show_ui'               => true,
				'query_var'             => true,
				'capabilities'          => array(
					'manage_terms' => 'manage_product_terms',
					'edit_terms'   => 'edit_product_terms',
					'delete_terms' => 'delete_product_terms',
					'assign_terms' => 'assign_product_terms',
				),
				'rewrite'               => array(
					'slug'         => empty( $permalinks['category_base'] ) ? _x( 'product-category', 'slug', 'woocommerce' ) : $permalinks['category_base'],
					'with_front'   => false,
					'hierarchical' => true,
				),
			) )
		);

		register_taxonomy( 'product_tag',
			apply_filters( 'woocommerce_taxonomy_objects_product_tag', array( 'product' ) ),
			apply_filters( 'woocommerce_taxonomy_args_product_tag', array(
				'hierarchical'          => false,
				'update_count_callback' => '_wc_term_recount',
				'label'                 => __( 'Product Tags', 'woocommerce' ),
				'labels'                => array(
						'name'                       => __( 'Product Tags', 'woocommerce' ),
						'singular_name'              => __( 'Product Tag', 'woocommerce' ),
						'menu_name'                  => _x( 'Tags', 'Admin menu name', 'woocommerce' ),
						'search_items'               => __( 'Search Product Tags', 'woocommerce' ),
						'all_items'                  => __( 'All Product Tags', 'woocommerce' ),
						'edit_item'                  => __( 'Edit Product Tag', 'woocommerce' ),
						'update_item'                => __( 'Update Product Tag', 'woocommerce' ),
						'add_new_item'               => __( 'Add New Product Tag', 'woocommerce' ),
						'new_item_name'              => __( 'New Product Tag Name', 'woocommerce' ),
						'popular_items'              => __( 'Popular Product Tags', 'woocommerce' ),
						'separate_items_with_commas' => __( 'Separate Product Tags with commas', 'woocommerce'  ),
						'add_or_remove_items'        => __( 'Add or remove Product Tags', 'woocommerce' ),
						'choose_from_most_used'      => __( 'Choose from the most used Product tags', 'woocommerce' ),
						'not_found'                  => __( 'No Product Tags found', 'woocommerce' ),
					),
				'show_ui'               => true,
				'query_var'             => true,
				'capabilities'          => array(
					'manage_terms' => 'manage_product_terms',
					'edit_terms'   => 'edit_product_terms',
					'delete_terms' => 'delete_product_terms',
					'assign_terms' => 'assign_product_terms',
				),
				'rewrite'               => array(
					'slug'       => empty( $permalinks['tag_base'] ) ? _x( 'product-tag', 'slug', 'woocommerce' ) : $permalinks['tag_base'],
					'with_front' => false
				),
			) )
		);

		register_taxonomy( 'product_shipping_class',
			apply_filters( 'woocommerce_taxonomy_objects_product_shipping_class', array('product', 'product_variation') ),
			apply_filters( 'woocommerce_taxonomy_args_product_shipping_class', array(
				'hierarchical'          => true,
				'update_count_callback' => '_update_post_term_count',
				'label'                 => __( 'Shipping Classes', 'woocommerce' ),
				'labels' => array(
						'name'              => __( 'Shipping Classes', 'woocommerce' ),
						'singular_name'     => __( 'Shipping Class', 'woocommerce' ),
						'menu_name'         => _x( 'Shipping Classes', 'Admin menu name', 'woocommerce' ),
						'search_items'      => __( 'Search Shipping Classes', 'woocommerce' ),
						'all_items'         => __( 'All Shipping Classes', 'woocommerce' ),
						'parent_item'       => __( 'Parent Shipping Class', 'woocommerce' ),
						'parent_item_colon' => __( 'Parent Shipping Class:', 'woocommerce' ),
						'edit_item'         => __( 'Edit Shipping Class', 'woocommerce' ),
						'update_item'       => __( 'Update Shipping Class', 'woocommerce' ),
						'add_new_item'      => __( 'Add New Shipping Class', 'woocommerce' ),
						'new_item_name'     => __( 'New Shipping Class Name', 'woocommerce' )
					),
				'show_ui'               => false,
				'show_in_nav_menus'     => false,
				'query_var'             => is_admin(),
				'capabilities'          => array(
					'manage_terms' => 'manage_product_terms',
					'edit_terms'   => 'edit_product_terms',
					'delete_terms' => 'delete_product_terms',
					'assign_terms' => 'assign_product_terms',
				),
				'rewrite'               => false,
			) )
		);

		global $wc_product_attributes;

		$wc_product_attributes = array();

		if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) {
			foreach ( $attribute_taxonomies as $tax ) {
				if ( $name = wc_attribute_taxonomy_name( $tax->attribute_name ) ) {
					$tax->attribute_public          = absint( isset( $tax->attribute_public ) ? $tax->attribute_public : 1 );
					$label                          = ! empty( $tax->attribute_label ) ? $tax->attribute_label : $tax->attribute_name;
					$wc_product_attributes[ $name ] = $tax;
					$taxonomy_data                  = array(
						'hierarchical'          => true,
						'update_count_callback' => '_update_post_term_count',
						'labels'                => array(
								'name'              => $label,
								'singular_name'     => $label,
								'search_items'      => sprintf( __( 'Search %s', 'woocommerce' ), $label ),
								'all_items'         => sprintf( __( 'All %s', 'woocommerce' ), $label ),
								'parent_item'       => sprintf( __( 'Parent %s', 'woocommerce' ), $label ),
								'parent_item_colon' => sprintf( __( 'Parent %s:', 'woocommerce' ), $label ),
								'edit_item'         => sprintf( __( 'Edit %s', 'woocommerce' ), $label ),
								'update_item'       => sprintf( __( 'Update %s', 'woocommerce' ), $label ),
								'add_new_item'      => sprintf( __( 'Add New %s', 'woocommerce' ), $label ),
								'new_item_name'     => sprintf( __( 'New %s', 'woocommerce' ), $label )
							),
						'show_ui'           => false,
						'query_var'         => 1 === $tax->attribute_public,
						'rewrite'           => false,
						'sort'              => false,
						'public'            => 1 === $tax->attribute_public,
						'show_in_nav_menus' => 1 === $tax->attribute_public && apply_filters( 'woocommerce_attribute_show_in_nav_menus', false, $name ),
						'capabilities'      => array(
							'manage_terms' => 'manage_product_terms',
							'edit_terms'   => 'edit_product_terms',
							'delete_terms' => 'delete_product_terms',
							'assign_terms' => 'assign_product_terms',
						)
					);

					if ( 1 === $tax->attribute_public ) {
						$taxonomy_data['rewrite'] = array(
							'slug'         => empty( $permalinks['attribute_base'] ) ? '' : trailingslashit( $permalinks['attribute_base'] ) . sanitize_title( $tax->attribute_name ),
							'with_front'   => false,
							'hierarchical' => true
						);
					}

					register_taxonomy( $name, apply_filters( "woocommerce_taxonomy_objects_{$name}", array( 'product' ) ), apply_filters( "woocommerce_taxonomy_args_{$name}", $taxonomy_data ) );
				}
			}

			do_action( 'woocommerce_after_register_taxonomy' );
		}
	}

	/**
	 * Register core post types.
	 */
	public static function register_post_types() {
		if ( post_type_exists('product') ) {
			return;
		}

		do_action( 'woocommerce_register_post_type' );

		$permalinks        = get_option( 'woocommerce_permalinks' );
		$product_permalink = empty( $permalinks['product_base'] ) ? _x( 'product', 'slug', 'woocommerce' ) : $permalinks['product_base'];

		register_post_type( 'product',
			apply_filters( 'woocommerce_register_post_type_product',
				array(
					'labels'              => array(
							'name'                  => __( 'Products', 'woocommerce' ),
							'singular_name'         => __( 'Product', 'woocommerce' ),
							'menu_name'             => _x( 'Products', 'Admin menu name', 'woocommerce' ),
							'add_new'               => __( 'Add Product', 'woocommerce' ),
							'add_new_item'          => __( 'Add New Product', 'woocommerce' ),
							'edit'                  => __( 'Edit', 'woocommerce' ),
							'edit_item'             => __( 'Edit Product', 'woocommerce' ),
							'new_item'              => __( 'New Product', 'woocommerce' ),
							'view'                  => __( 'View Product', 'woocommerce' ),
							'view_item'             => __( 'View Product', 'woocommerce' ),
							'search_items'          => __( 'Search Products', 'woocommerce' ),
							'not_found'             => __( 'No Products found', 'woocommerce' ),
							'not_found_in_trash'    => __( 'No Products found in trash', 'woocommerce' ),
							'parent'                => __( 'Parent Product', 'woocommerce' ),
							'featured_image'        => __( 'Product Image', 'woocommerce' ),
							'set_featured_image'    => __( 'Set product image', 'woocommerce' ),
							'remove_featured_image' => __( 'Remove product image', 'woocommerce' ),
							'use_featured_image'    => __( 'Use as product image', 'woocommerce' ),
						),
					'description'         => __( 'This is where you can add new products to your store.', 'woocommerce' ),
					'public'              => true,
					'show_ui'             => true,
					'capability_type'     => 'product',
					'map_meta_cap'        => true,
					'publicly_queryable'  => true,
					'exclude_from_search' => false,
					'hierarchical'        => false, // Hierarchical causes memory issues - WP loads all records!
					'rewrite'             => $product_permalink ? array( 'slug' => untrailingslashit( $product_permalink ), 'with_front' => false, 'feeds' => true ) : false,
					'query_var'           => true,
					'supports'            => array( 'title', 'editor', 'excerpt', 'thumbnail', 'comments', 'custom-fields', 'page-attributes', 'publicize', 'wpcom-markdown' ),
					'has_archive'         => ( $shop_page_id = wc_get_page_id( 'shop' ) ) && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop',
					'show_in_nav_menus'   => true
				)
			)
		);

		register_post_type( 'product_variation',
			apply_filters( 'woocommerce_register_post_type_product_variation',
				array(
					'label'        => __( 'Variations', 'woocommerce' ),
					'public'       => false,
					'hierarchical' => false,
					'supports'     => false,
					'capability_type' => 'product'
				)
			)
		);

		wc_register_order_type(
			'shop_order',
			apply_filters( 'woocommerce_register_post_type_shop_order',
				array(
					'labels'              => array(
							'name'               => __( 'Orders', 'woocommerce' ),
							'singular_name'      => __( 'Order', 'woocommerce' ),
							'add_new'            => __( 'Add Order', 'woocommerce' ),
							'add_new_item'       => __( 'Add New Order', 'woocommerce' ),
							'edit'               => __( 'Edit', 'woocommerce' ),
							'edit_item'          => __( 'Edit Order', 'woocommerce' ),
							'new_item'           => __( 'New Order', 'woocommerce' ),
							'view'               => __( 'View Order', 'woocommerce' ),
							'view_item'          => __( 'View Order', 'woocommerce' ),
							'search_items'       => __( 'Search Orders', 'woocommerce' ),
							'not_found'          => __( 'No Orders found', 'woocommerce' ),
							'not_found_in_trash' => __( 'No Orders found in trash', 'woocommerce' ),
							'parent'             => __( 'Parent Orders', 'woocommerce' ),
							'menu_name'          => _x( 'Orders', 'Admin menu name', 'woocommerce' )
						),
					'description'         => __( 'This is where store orders are stored.', 'woocommerce' ),
					'public'              => false,
					'show_ui'             => true,
					'capability_type'     => 'shop_order',
					'map_meta_cap'        => true,
					'publicly_queryable'  => false,
					'exclude_from_search' => true,
					'show_in_menu'        => current_user_can( 'manage_woocommerce' ) ? 'woocommerce' : true,
					'hierarchical'        => false,
					'show_in_nav_menus'   => false,
					'rewrite'             => false,
					'query_var'           => false,
					'supports'            => array( 'title', 'comments', 'custom-fields' ),
					'has_archive'         => false,
				)
			)
		);

		wc_register_order_type(
			'shop_order_refund',
			apply_filters( 'woocommerce_register_post_type_shop_order_refund',
				array(
					'label'                            => __( 'Refunds', 'woocommerce' ),
					'capability_type'                  => 'shop_order',
					'public'                           => false,
					'hierarchical'                     => false,
					'supports'                         => false,
					'exclude_from_orders_screen'       => false,
					'add_order_meta_boxes'             => false,
					'exclude_from_order_count'         => true,
					'exclude_from_order_views'         => false,
					'exclude_from_order_reports'       => false,
					'exclude_from_order_sales_reports' => true,
					'class_name'                       => 'WC_Order_Refund'
				)
			)
		);

		if ( 'yes' == get_option( 'woocommerce_enable_coupons' ) ) {
			register_post_type( 'shop_coupon',
				apply_filters( 'woocommerce_register_post_type_shop_coupon',
					array(
						'labels'              => array(
								'name'               => __( 'Coupons', 'woocommerce' ),
								'singular_name'      => __( 'Coupon', 'woocommerce' ),
								'menu_name'          => _x( 'Coupons', 'Admin menu name', 'woocommerce' ),
								'add_new'            => __( 'Add Coupon', 'woocommerce' ),
								'add_new_item'       => __( 'Add New Coupon', 'woocommerce' ),
								'edit'               => __( 'Edit', 'woocommerce' ),
								'edit_item'          => __( 'Edit Coupon', 'woocommerce' ),
								'new_item'           => __( 'New Coupon', 'woocommerce' ),
								'view'               => __( 'View Coupons', 'woocommerce' ),
								'view_item'          => __( 'View Coupon', 'woocommerce' ),
								'search_items'       => __( 'Search Coupons', 'woocommerce' ),
								'not_found'          => __( 'No Coupons found', 'woocommerce' ),
								'not_found_in_trash' => __( 'No Coupons found in trash', 'woocommerce' ),
								'parent'             => __( 'Parent Coupon', 'woocommerce' )
							),
						'description'         => __( 'This is where you can add new coupons that customers can use in your store.', 'woocommerce' ),
						'public'              => false,
						'show_ui'             => true,
						'capability_type'     => 'shop_coupon',
						'map_meta_cap'        => true,
						'publicly_queryable'  => false,
						'exclude_from_search' => true,
						'show_in_menu'        => current_user_can( 'manage_woocommerce' ) ? 'woocommerce' : true,
						'hierarchical'        => false,
						'rewrite'             => false,
						'query_var'           => false,
						'supports'            => array( 'title' ),
						'show_in_nav_menus'   => false,
						'show_in_admin_bar'   => true
					)
				)
			);
		}

		register_post_type( 'shop_webhook',
			apply_filters( 'woocommerce_register_post_type_shop_webhook',
				array(
					'labels'              => array(
						'name'               => __( 'Webhooks', 'woocommerce' ),
						'singular_name'      => __( 'Webhook', 'woocommerce' ),
						'menu_name'          => _x( 'Webhooks', 'Admin menu name', 'woocommerce' ),
						'add_new'            => __( 'Add Webhook', 'woocommerce' ),
						'add_new_item'       => __( 'Add New Webhook', 'woocommerce' ),
						'edit'               => __( 'Edit', 'woocommerce' ),
						'edit_item'          => __( 'Edit Webhook', 'woocommerce' ),
						'new_item'           => __( 'New Webhook', 'woocommerce' ),
						'view'               => __( 'View Webhooks', 'woocommerce' ),
						'view_item'          => __( 'View Webhook', 'woocommerce' ),
						'search_items'       => __( 'Search Webhooks', 'woocommerce' ),
						'not_found'          => __( 'No Webhooks found', 'woocommerce' ),
						'not_found_in_trash' => __( 'No Webhooks found in trash', 'woocommerce' ),
						'parent'             => __( 'Parent Webhook', 'woocommerce' )
					),
					'public'              => false,
					'show_ui'             => false,
					'capability_type'     => 'shop_webhook',
					'map_meta_cap'        => true,
					'publicly_queryable'  => false,
					'exclude_from_search' => true,
					'show_in_menu'        => false,
					'hierarchical'        => false,
					'rewrite'             => false,
					'query_var'           => false,
					'supports'            => false,
					'show_in_nav_menus'   => false,
					'show_in_admin_bar'   => false
				)
			)
		);
	}

	/**
	 * Register our custom post statuses, used for order status.
	 */
	public static function register_post_status() {
		register_post_status( 'wc-pending', array(
			'label'                     => _x( 'Pending Payment', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Pending Payment (%s)', 'Pending Payment (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-processing', array(
			'label'                     => _x( 'Processing', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Processing (%s)', 'Processing (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-on-hold', array(
			'label'                     => _x( 'On Hold', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'On Hold (%s)', 'On Hold (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-completed', array(
			'label'                     => _x( 'Completed', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Completed (%s)', 'Completed (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-cancelled', array(
			'label'                     => _x( 'Cancelled', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Cancelled (%s)', 'Cancelled (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-refunded', array(
			'label'                     => _x( 'Refunded', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Refunded (%s)', 'Refunded (%s)', 'woocommerce' )
		) );
		register_post_status( 'wc-failed', array(
			'label'                     => _x( 'Failed', 'Order status', 'woocommerce' ),
			'public'                    => false,
			'exclude_from_search'       => false,
			'show_in_admin_all_list'    => true,
			'show_in_admin_status_list' => true,
			'label_count'               => _n_noop( 'Failed (%s)', 'Failed (%s)', 'woocommerce' )
		) );
	}

	/**
	 * Add Product Support to Jetpack Omnisearch.
	 */
	public static function support_jetpack_omnisearch() {
		if ( class_exists( 'Jetpack_Omnisearch_Posts' ) ) {
			new Jetpack_Omnisearch_Posts( 'product' );
		}
	}

	/**
	 * Added product for Jetpack related posts
	 *
	 * @param  array $post_types
	 * @return array
	 */
	public static function rest_api_allowed_post_types( $post_types ) {
		$post_types[] = 'product';

		return $post_types;
	}
}

WC_Post_types::init();


text:
      COVID-19 epidemiologic status in Castilla y León (last update 17/03/2020)

  <ods-dataset-context context="regions, cases, selected" cases-domain="jcyl" cases-dataset="situacion-epidemiologica-coronavirus-en-castilla-y-leon" selected-domain="jcyl"
    selected-dataset="situacion-epidemiologica-coronavirus-en-castilla-y-leon" selected-parameters="{'disjunctive.provincia':true}" regions-dataset="limites-provinciales-de-castilla-y-leon-recintos"
    regions-domain="jcyl">

    {{ nbRecords = byDate.results.length - 1; "" }}

      {{ lastDate = list[list.length-1].fields.fecha; "" }}
      {{ cases.parameters['refine.fecha'] = lastDate;""}}

{{ byDate.results[nbRecords].confirmados }}

confirmed cases

{{ byDate.results[nbRecords].nuevos }}

confirmed new-cases today

{{ byDate.results[nbRecords].altas }}

Recovered

{{ byDate.results[nbRecords].fallecimientos }}

Fatalities

              Total cases

              New cases today

                  {{reg_code = res.codigos > 9999 ? (res.codigos | limitTo:2) : (res.codigos | limitTo:1); ""}}
                  {{colors[reg_code] = "hsl(220,75%," + (75 - ((res.confirmados - results[0].minval) / (results[0].maxval - results[0].minval) * 50) | number : 0) + "%,1)"; "" }}

              <ods-map basemap="jawg.light" no-refit="false" scroll-wheel-zoom="false" display-control="false" toolbar-drawing="false">

                <ods-map-layer context="cases" color="#142e7b" picto="ods-circle" display="clusters" function="SUM" expression="casos_confirmados" shape-opacity="0.5" point-opacity="1" caption="false"
                  title="Epidimioliogic satutus in Castilla dy Leon" size-min="3" size-max="5" size-function="linear"></ods-map-layer>
                <ods-map-layer context="regions" color-categories="colors" color-by-field="cod_ine_prov" color-categories-other="lightgrey" display="categories" shape-opacity="0.7" tooltip-disabled="true"></ods-map-layer>
              </ods-map>

                  {{reg_code = res.codigos > 9999 ? (res.codigos | limitTo:2) : (res.codigos | limitTo:1); ""}}
                  {{colors[reg_code] = "hsl(220,75%," + (75 - ((res.nuevos - results[0].minval) / (results[0].maxval - results[0].minval) * 50) | number : 0) + "%,1)"; "" }}

            <ods-map basemap="jawg.light" no-refit="false" scroll-wheel-zoom="false" display-control="false" toolbar-drawing="false">
              <ods-map-layer context="cases" color="#142e7b" picto="ods-circle" display="clusters" function="SUM" expression="nuevos_positivos" shape-opacity="0.5" point-opacity="1" caption="false" title="Epidimioliogic satutus in Castilla dy Leon"
                size-min="3" size-max="5" size-function="linear"></ods-map-layer>
              <ods-map-layer context="regions" color-categories="colors" color-by-field="cod_ine_prov" color-categories-other="lightgrey" display="categories" shape-opacity="0.7" tooltip-disabled="true"></ods-map-layer>
            </ods-map>

              Region
              Confirmed
              Recovered
              Deaths

                    <input id="{{ region.x }}" type="checkbox" class="hidden-checkbox" ods-toggle-model="$parent.selected.parameters" ods-toggle-key="refine.provincia" ods-toggle-value="{{ region.x }}" />

                    {{ region.x }}

                {{ region.confirmados }}
                {{ region.altas }}
                {{ region.fallecimientos }}

Evolution

          <ods-chart timescale="year" single-y-axis="true" scientific-display="false" align-month="true">
            <ods-chart-query context="selected" field-x="fecha" maxpoints="0" timescale="day">
              <ods-chart-serie expression-y="casos_confirmados" chart-type="spline" function-y="SUM" label-y="Confirmed cases" color="#00c7b1" scientific-display="true" display-values="true">
              </ods-chart-serie>
              <ods-chart-serie expression-y="fallecimientos" chart-type="line" function-y="SUM" label-y="Deceased" color="#fc8d62" scientific-display="true" display-values="true">
              </ods-chart-serie>
            </ods-chart-query>
          </ods-chart>

Daily Increment

          <ods-chart timescale="year" align-month="true">
            <ods-chart-query context="selected" field-x="fecha" maxpoints="0" timescale="day">
              <ods-chart-serie expression-y="nuevos_positivos" chart-type="column" function-y="SUM" label-y="New positives" color="#00c7b1" display-values="true" display-stack-values="false" scientific-display="true">
              </ods-chart-serie>
            </ods-chart-query>
          </ods-chart>

  </ods-dataset-context>

redpajama_set_name: RedPajamaGithub


text:
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.rpc;

import com.yahoo.concurrent.ThreadFactoryFactory;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.jrt.Target;
import com.yahoo.jrt.TargetWatcher;
import com.yahoo.vespa.config.protocol.JRTServerConfigRequest;
import com.yahoo.vespa.config.server.GetConfigContext;
import com.yahoo.vespa.config.server.monitoring.MetricUpdater;
import com.yahoo.vespa.config.server.monitoring.Metrics;
import com.yahoo.vespa.config.server.tenant.TenantRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Takes care of <i>delayed responses</i> in the config server.
 * A delayed response is a response sent at request (server) timeout
 * for a config which has not changed since the request was initiated.
 *
 * @author hmusum
 */
public class DelayedConfigResponses {
    private static final Logger log = Logger.getLogger(DelayedConfigResponses.class.getName());
    private final RpcServer rpcServer;

    private final ScheduledExecutorService executorService;
    private final boolean useJrtWatcher;

    private final Map<ApplicationId, MetricUpdater> metrics = new ConcurrentHashMap<>();

    /* Requests that resolve to config that has not changed are put on this queue. When activating
       config, all requests on this queue are reprocessed as if they were a new request */
    private final Map<ApplicationId, BlockingQueue<DelayedConfigResponse>> delayedResponses =
            new ConcurrentHashMap<>();

    DelayedConfigResponses(RpcServer rpcServer, int numTimerThreads) {
        this(rpcServer, numTimerThreads, true);
    }

    // Since JRT does not allow adding watcher for "fake" requests, we must be able to disable it for unit tests :(
    DelayedConfigResponses(RpcServer rpcServer, int numTimerThreads, boolean useJrtWatcher) {
        this.rpcServer = rpcServer;
        ScheduledThreadPoolExecutor executor =
                new ScheduledThreadPoolExecutor(numTimerThreads,
                                                ThreadFactoryFactory.getDaemonThreadFactory("delayed config responses"));
        executor.setRemoveOnCancelPolicy(true);
        this.executorService = executor;
        this.useJrtWatcher = useJrtWatcher;
    }

    List<DelayedConfigResponse> allDelayedResponses() {
        List<DelayedConfigResponse> responses = new ArrayList<>();
        for (Map.Entry<ApplicationId, BlockingQueue<DelayedConfigResponse>> entry : delayedResponses.entrySet()) {
            responses.addAll(entry.getValue());
        }
        return responses;
    }

    /**
     * The run method of this class is run by a Timer when the timeout expires.
     * The timer associated with this response must be cancelled first.
     */
    class DelayedConfigResponse implements Runnable, TargetWatcher {

        final JRTServerConfigRequest request;
        private final BlockingQueue<DelayedConfigResponse> delayedResponsesQueue;
        private final ApplicationId app;
        private ScheduledFuture<?> future;

        DelayedConfigResponse(JRTServerConfigRequest req, BlockingQueue<DelayedConfigResponse> delayedResponsesQueue, ApplicationId app) {
            this.request = req;
            this.delayedResponsesQueue = delayedResponsesQueue;
            this.app = app;
        }

        @Override
        public synchronized void run() {
            removeFromQueue();
            removeWatcher();
            rpcServer.addToRequestQueue(request, true, null);
            if (log.isLoggable(Level.FINE)) {
                log.log(Level.FINE, logPre()+"DelayedConfigResponse. putting on queue: " + request.getShortDescription());
            }
        }

        /**
         * Remove delayed response from its queue
         */
        private void removeFromQueue() {
            delayedResponsesQueue.remove(this);
        }

        JRTServerConfigRequest getRequest() {
            return request;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("Delayed response for ").append(logPre()).append(request.getShortDescription());
            return sb.toString();
        }

        String logPre() {
            return TenantRepository.logPre(app);
        }

        synchronized void cancelAndRemove() {
            removeFromQueue();
            cancel();
        }

        synchronized boolean cancel() {
            removeWatcher();
            if (future == null) {
                throw new IllegalStateException("Cannot cancel a task that has not been scheduled");
            }
            return future.cancel(false);
        }

        synchronized void schedule(long delay) throws InterruptedException {
            delayedResponsesQueue.put(this);
            future = executorService.schedule(this, delay, TimeUnit.MILLISECONDS);
            addWatcher();
        }

        /**
         * Removes this delayed response if target is invalid.
         *
         * @param target a Target that has become invalid (i.e, client has closed connection)
         * @see DelayedConfigResponses
         */
        @Override
        public void notifyTargetInvalid(Target target) {
            cancelAndRemove();
        }

        private void addWatcher() {
            if (useJrtWatcher) {
                request.getRequest().target().addWatcher(this);
            }
        }

        private void removeWatcher() {
            if (useJrtWatcher) {
                request.getRequest().target().removeWatcher(this);
            }
        }
    }

    /**
     * Creates a DelayedConfigResponse object for taking care of requests that should
     * not be responded to right away.  Puts the object on the delayedResponsesQueue.
     *
     * NOTE: This method is called from multiple threads, so everything here needs to be
     * thread safe!
     *
     * @param request a JRTConfigRequest
     */
    final void delayResponse(JRTServerConfigRequest request, GetConfigContext context) {
        if (request.isDelayedResponse()) {
            log.log(Level.FINE, () -> context.logPre()+"Request already delayed");
        } else {
            createQueueIfNotExists(context);
            BlockingQueue<DelayedConfigResponse> delayedResponsesQueue = delayedResponses.get(context.applicationId());
            DelayedConfigResponse response = new DelayedConfigResponse(request, delayedResponsesQueue, context.applicationId());
            request.setDelayedResponse(true);
            try {
                if (log.isLoggable(Level.FINE)) {
                    log.log(Level.FINE, context.logPre()+"Putting on delayedRequests queue (" + delayedResponsesQueue.size() + " elements): " +
                            response.getRequest().getShortDescription());
                }
                // Config will be resolved in the run() method of DelayedConfigResponse,
                // when the timer expires or config is updated/activated.
                response.schedule(Math.max(0, request.getTimeout()));
                metricDelayedResponses(context.applicationId(), delayedResponsesQueue.size());
            } catch (InterruptedException e) {
                log.log(Level.WARNING, context.logPre()+"Interrupted when putting on delayed requests queue.");
            }
        }
    }

    private synchronized void metricDelayedResponses(ApplicationId app, int elems) {
        metrics.computeIfAbsent(app, key -> rpcServer.metricUpdaterFactory()
                                                     .getOrCreateMetricUpdater(Metrics.createDimensions(key)))
               .setDelayedResponses(elems);
    }

    private synchronized void createQueueIfNotExists(GetConfigContext context) {
        if ( ! delayedResponses.containsKey(context.applicationId())) {
            delayedResponses.put(context.applicationId(), new LinkedBlockingQueue<>());
        }
    }

    void stop() {
        executorService.shutdown();
    }

    /**
     * Drains delayed responses queue and returns responses in an array
     *
     * @return and array of DelayedConfigResponse objects
     */
    List<DelayedConfigResponse> drainQueue(ApplicationId app) {
        ArrayList<DelayedConfigResponse> ret = new ArrayList<>();

        if (delayedResponses.containsKey(app)) {
            BlockingQueue<DelayedConfigResponse> queue = delayedResponses.get(app);
            queue.drainTo(ret);
        }
        metrics.remove(app);
        return ret;
    }

    @Override
    public String toString() {
        return "DelayedConfigResponses. Average Size=" + size();
    }

    int size() {
        int totalQueueSize = 0;
        int numQueues = 0;
        for (Map.Entry<ApplicationId, BlockingQueue<DelayedConfigResponse>> e : delayedResponses.entrySet()) {
            numQueues++;
            totalQueueSize+=e.getValue().size();
        }
        return (numQueues > 0) ? (totalQueueSize / numQueues) : 0;
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<FindbugsPlugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://findbugs.googlecode.com/svn/trunk/findbugs/etc/findbugsplugin.xsd"
        pluginid="jp.co.minori.findbugs"
        provider="Minori"
        website="https://github.com/crow-misia/FindBugsPlugin">

        <Detector class="jp.co.minori.findbugs.detect.slf4j.WrongPlaceholderDetector" reports="SLF4J_PLACE_HOLDER_MISMATCH,SLF4J_UNKNOWN_ARRAY,SLF4J_UNKNOWN_ARRAY,SLF4J_SIGN_ONLY_FORMAT,SLF4J_FORMAT_SHOULD_BE_CONST" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.slf4j.PublishedLoggerDetector" reports="SLF4J_LOGGER_SHOULD_BE_PRIVATE" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.slf4j.NonFinalLoggerDetector" reports="SLF4J_LOGGER_SHOULD_BE_FINAL" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.slf4j.IllegalPassedClassDetector" reports="SLF4J_ILLEGAL_PASSED_CLASS" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.slf4j.LogNestDetector" reports="SLF4J_LOG_NEST_IS_METHOD" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.slf4j.LogLevelUnmatchDetector" reports="SLF4J_LOG_LEVEL_UNMATCH" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.debug.Print" reports="DEBUG_PRINT" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.sil.PrintStackTrace" reports="SIL_PRINT_STACK_TRACE" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.cn.ConfusingNaming" reports="CN_CONFUSING_NAMING" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.uoe.UseObjectEquals" reports="UOE_USE_OBJECT_EQUALS" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.oes.EmptyString" reports="OES_PRINTLN_EMPTY_STRING,OES_PRINT_EMPTY_STRING" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.java6.PropertiesEncoding" reports="JAVA6_PROPERTIES_ENCODING" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.java7.CatchMultiple" reports="JAVA7_CATCH_MULTIPLE_MERGE" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.ics.InefficientConvertString" reports="IS_INEFFICIENT_CONVERT_STRING" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.i18n.ByteArrayOutputStreamEncoding" reports="I18N_BYTE_ARRAY_OUTPUT_STREAM_ENCODING" speed="fast" />

        <Detector class="jp.co.minori.findbugs.detect.sc.MET03J" reports="SC_MET03J" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.sc.DCL02J" reports="SC_DCL02J" speed="fast" />
        <Detector class="jp.co.minori.findbugs.detect.sc.NUM02J" reports="SC_NUM02J_ZERO,SC_NUM02J_NOT_ZERO_CHECK" speed="fast" />

        <BugPattern type="SLF4J_PLACE_HOLDER_MISMATCH" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_FORMAT_SHOULD_BE_CONST" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_UNKNOWN_ARRAY" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_LOGGER_SHOULD_BE_PRIVATE" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_LOGGER_SHOULD_BE_FINAL" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_ILLEGAL_PASSED_CLASS" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_SIGN_ONLY_FORMAT" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_LOG_NEST_IS_METHOD" abbrev="SLF4J" category="CORRECTNESS" />
        <BugPattern type="SLF4J_LOG_LEVEL_UNMATCH" abbrev="SLF4J" category="CORRECTNESS" />

        <BugPattern type="DEBUG_PRINT" abbrev="DEBUG" category="CORRECTNESS" />

        <BugPattern type="SIL_PRINT_STACK_TRACE" abbrev="SIL" category="SECURITY" />

        <BugPattern type="CN_CONFUSING_NAMING" abbrev="CN" category="STYLE" />

        <BugPattern type="UOE_USE_OBJECT_EQUALS" abbrev="UOE" category="CORRECTNESS" />

        <BugPattern type="OES_PRINTLN_EMPTY_STRING" abbrev="OES" category="PERFORMANCE" />
        <BugPattern type="OES_PRINT_EMPTY_STRING" abbrev="OES" category="PERFORMANCE" />

        <BugPattern type="JAVA6_PROPERTIES_ENCODING" abbrev="JAVA6" category="BAD_PRACTICE" />

        <BugPattern type="JAVA7_CATCH_MULTIPLE_MERGE" abbrev="JAVA7" category="BAD_PRACTICE" />

        <BugPattern type="ICS_INEFFICIENT_CONVERT_STRING" abbrev="ICS" category="PERFORMANCE" />

        <BugPattern type="I18N_BYTE_ARRAY_OUTPUT_STREAM_ENCODING" abbrev="I18N" category="BAD_PRACTICE" />

        <BugPattern type="SC_MET03J" abbrev="SC" category="SECURITY" />
        <BugPattern type="SC_DCL02J" abbrev="SC" category="SECURITY" />
        <BugPattern type="SC_NUM02J_ZERO" abbrev="SC" category="SECURITY" />
        <BugPattern type="SC_NUM02J_NOT_ZERO_CHECK" abbrev="SC" category="SECURITY" />
</FindbugsPlugin>


text:
import io
import os
from os.path import join
import tempfile
import unittest
import shutil
from satella.files import read_re_sub_and_write, find_files, split, read_in_file, write_to_file, \
    write_out_file_if_different, make_noncolliding_name, try_unlink, DevNullFilelikeObject, \
    read_lines

def putfile(path: str) -> None:
    with open(path, 'wb') as f_out:
        f_out.write(b'\x32')

class TestFiles(unittest.TestCase):

    def test_read_nonexistent_file(self):
        self.assertRaises(FileNotFoundError, lambda: read_in_file('moot'))

    def test_read_lines(self):
        lines = read_lines('LICENSE')
        self.assertTrue(all(lines))

        with open('test.tmp', 'w') as f_out:
            f_out.write('''line1
            line2
            line3

            ''')

        self.assertEqual(read_lines('test.tmp'), ['line1', 'line2', 'line3'])

    def test_devnullfilelikeobject(self):
        null = DevNullFilelikeObject()
        self.assertEqual(null.write('ala'), 3)
        self.assertEqual(null.write(b'ala'), 3)
        self.assertRaises(io.UnsupportedOperation, lambda: null.read())
        self.assertRaises(io.UnsupportedOperation, lambda: null.read(7))
        null.flush()
        null.close()
        self.assertRaises(ValueError, lambda: null.write('test'))
        self.assertRaises(ValueError, lambda: null.flush())
        self.assertRaises(ValueError, lambda: null.read())
        null.close()

    def try_directory(self):
        os.system('mkdir test')
        self.assertRaises(FileNotFoundError, lambda: read_in_file('test'))
        self.assertEqual(b'test', read_in_file('test', default=b'test'))
        os.system('rm -rf test')
        self.assertRaises(FileNotFoundError, lambda: read_in_file('test'))
        self.assertEqual(b'test', read_in_file('test', default=b'test'))

    def test_make_noncolliding_name(self):
        with open('test.txt', 'w') as f_out:
            f_out.write('test')
        self.assertEqual(make_noncolliding_name('test.txt'), 'test.1.txt')
        self.assertTrue(try_unlink('test.txt'))
        self.assertFalse(try_unlink('test.txt'))

    def test_write_out_file_if_different(self):
        try:
            self.assertTrue(write_out_file_if_different('test', 'test', 'UTF-8'))
            self.assertFalse(write_out_file_if_different('test', 'test', 'UTF-8'))
        finally:
            os.unlink('test')

    def test_read_in_and_write_to(self):
        data = 'żażółć gęślą jaźń'
        write_to_file('temp.tmp', data, 'UTF-8')
        data2 = read_in_file('temp.tmp', 'UTF-8')
        self.assertEqual(data, data2)

    def test_split(self):
        self.assertIn(split('c:/windows/system32/system32.exe'), [['c:', 'windows', 'system32',
                                                                     'system32.exe'],
                                                                  ['c:/', 'windows', 'system32',
                                                                   'system32.exe']
                                                                  ])
        self.assertEqual(split('~/user/something/./else'), ['~', 'user', 'something', '.',
                                                            'else'])

    def setUp(self) -> None:
        self.filename = tempfile.mktemp()

    def tearDown(self) -> None:
        try:
            os.unlink(self.filename)
        except OSError:
            pass

    def test_find_files(self):
        directory = tempfile.mkdtemp()
        os.mkdir(join(directory, 'test'))
        putfile(join(directory, 'test', 'test.txt'))
        os.mkdir(join(directory, 'test', 'test'))
        putfile(join(directory, 'test', 'test', 'test.txt'))
        putfile(join(directory, 'test', 'test', 'test2.txt'))
        self.assertEqual(set(find_files(directory, r'(.*)test(.*)\.txt',
                                         apply_wildcard_to_entire_path=True)), {
            join(directory, 'test', 'test.txt'),
            join(directory, 'test', 'test', 'test.txt'),
            join(directory, 'test', 'test', 'test2.txt')
        })

        self.assertEqual(set(find_files(directory, r'(.*)\.txt')), {
            join(directory, 'test', 'test.txt'),
            join(directory, 'test', 'test', 'test.txt'),
            join(directory, 'test', 'test', 'test2.txt')
        })
        shutil.rmtree(directory)

    def test_read_re_sub_and_write(self):
        with open(self.filename, 'w') as f_out:
            f_out.write('RE')

        read_re_sub_and_write(self.filename, r'RE', 'sub')

        with open(self.filename, 'r') as f_in:
            self.assertEqual('sub', f_in.read())

    def test_read_re_sub_and_write_2(self):
        with open(self.filename, 'w') as f_out:
            f_out.write('{2} {3}')

        read_re_sub_and_write(self.filename, r'{(.*?)}', lambda match_obj: match_obj.group(1))

        with open(self.filename, 'r') as f_in:
            self.assertEqual('2 3', f_in.read())


text:
package shark.optimizer

import java.util.{LinkedHashMap => JavaLinkedHashMap}

import org.apache.hadoop.hive.ql.exec.{MapJoinOperator, JoinOperator, Operator}
import org.apache.hadoop.hive.ql.optimizer.MapJoinProcessor
import org.apache.hadoop.hive.ql.parse.{ParseContext, QBJoinTree, OpParseContext}
import org.apache.hadoop.hive.ql.plan.OperatorDesc
import org.apache.hadoop.hive.conf.HiveConf

class SharkMapJoinProcessor extends MapJoinProcessor {

  /**
   * Override generateMapJoinOperator to bypass the step of validating Map Join hints int Hive.
   */
  override def generateMapJoinOperator(
      pctx: ParseContext,
      op: JoinOperator,
      joinTree: QBJoinTree,
      mapJoinPos: Int): MapJoinOperator = {
    val hiveConf: HiveConf = pctx.getConf
    val noCheckOuterJoin: Boolean =
      HiveConf.getBoolVar(hiveConf, HiveConf.ConfVars.HIVEOPTSORTMERGEBUCKETMAPJOIN) &&
      HiveConf.getBoolVar(hiveConf, HiveConf.ConfVars.HIVEOPTBUCKETMAPJOIN)

    val opParseCtxMap: JavaLinkedHashMap[Operator[_ <: OperatorDesc], OpParseContext] =
      pctx.getOpParseCtx

    // Explicitly set validateMapJoinTree to false to bypass the step of validating
    // Map Join hints in Hive.
    val validateMapJoinTree = false
    val mapJoinOp: MapJoinOperator =
      MapJoinProcessor.convertMapJoin(
        opParseCtxMap, op, joinTree, mapJoinPos, noCheckOuterJoin, validateMapJoinTree)

    // Hive originally uses genSelectPlan to insert an dummy select after the MapJoinOperator.
    // We should not need this step.
    // create a dummy select to select all columns
    // MapJoinProcessor.genSelectPlan(pctx, mapJoinOp)

    return mapJoinOp
  }
}


text:
from __future__ import print_function
import re
import sys

categories = []
defines = []
excludes = []
bases = []

if __name__ == '__main__':
  out = sys.stdout
  filenames = sys.argv[1:]

  while filenames and filenames[0].startswith('-'):
    option = filenames.pop(0)
    if option == '-o': out = open(filenames.pop(0), 'w')
    elif option.startswith('-C'): categories += option[2:].split(',')
    elif option.startswith('-D'): defines += option[2:].split(',')
    elif option.startswith('-X'): excludes += option[2:].split(',')
    elif option.startswith('-B'): bases += option[2:].split(',')

  excludes = map(re.compile, excludes)
  exported = []

  for filename in filenames:
    for line in open(filename).readlines():
      name, _, _, meta, _ = re.split('\s+', line)
      if any(map(lambda p: p.match(name), excludes)): continue
      meta = meta.split(':')
      assert meta[0] in ('EXIST', 'NOEXIST')
      assert meta[2] in ('FUNCTION', 'VARIABLE')
      if meta[0] != 'EXIST': continue
      if meta[2] != 'FUNCTION': continue
      def satisfy(expr, rules):
        def test(expr):
          if expr.startswith('!'): return not expr[1:] in rules
          return expr == '' or expr in rules
        return all(map(test, expr.split(',')))
      if not satisfy(meta[1], defines): continue
      if not satisfy(meta[3], categories): continue
      exported.append(name)

  for filename in bases:
    for line in open(filename).readlines():
      line = line.strip()
      if line == 'EXPORTS': continue
      if line[0] == ';': continue
      exported.append(line)

  print('EXPORTS', file=out)
  for name in sorted(exported): print('    ', name, file=out)


text:
class RemoveElasticBatchProjectIndexerWorkerQueue < ActiveRecord::Migration[6.0]
  DOWNTIME = false

  def up
    Sidekiq.redis do |conn|
      conn.del "queue:elastic_batch_project_indexer"
    end
  end
end


text:
layout: post
title: "Off to take dad to Tony Roma's..."
---
Off to take dad to Tony Roma's for father's day (he's working tomorrow)


text:
var canvas;
var context;

var loaded                  = false;

var interval                = 1.0 / 30.0;
var time                    = 0.0;

var xSize                   = 15;
var ySize                   = 8;

var cellTypeNone            = -1;
var cellTypeEmpty           = 0;
var cellTypeCorridor        = 1;
var cellTypeLeak            = 2;
var cellTypeDoorShut        = 3;
var cellTypeDoorOpen        = 4;

var interactModeBuild       = 0;
var interactModePlaceDoor   = 1;
var interactModePlaceLeak   = 2;

var noFloodGroup            = -1;
var noCompartment           = -1;

var compartmentStatusNoLeaks    = 0;
var compartmentStatusLeaks      = 1;

var cellType                = new Array(xSize * ySize);
var cellWaterLevel          = new Array(xSize * ySize);
var cellDelta               = new Array(xSize * ySize);
var cellFloodGroup          = new Array(xSize * ySize);
var cellCompartment         = new Array(xSize * ySize);
var floodGroupWaterLevel;
var floodGroupArea;
var compartmentStatus;

var cellSize                = 40;   // In pixels
var cellOverlap             = 10;   // In pixels.
var doorWidth               = 14;   // In pixels.

var controlPressed          = false;
var interactMode            = interactModeBuild;

var maxCompression          = 0.5;
var leakSpeed               = 4.0;
var flowRate                = 10.0;
var bulkheadFlowRate        = 1.0;
var drainRate               = 1.0 / 60.0;
var damageFlashFrequency    = 7;
var damageFlashAmount       = 0.15;

var globalWaterLevel        = 5.5;
var equalizeCompartments    = true;
var showPressure            = false;

var tilesImage;
var skyGradient;
var waterGradient;

function RenderCells()
{
    var sw = cellSize + cellOverlap * 2;
    var sh = cellSize + cellOverlap * 2;

    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            var c = cellType[x + y * xSize];

            if (c != cellTypeEmpty)
            {

                var n = IsInside(x, y - 1) ? 1 : 0;
                var s = IsInside(x, y + 1) ? 1 : 0;
                var e = IsInside(x + 1, y) ? 1 : 0;
                var w = IsInside(x - 1, y) ? 1 : 0;

                var dx = x * cellSize - cellOverlap;
                var dy = y * cellSize - cellOverlap;

                var tileIndex = n * 8 + e * 4 + s * 2 + w;

                var sy = tileIndex * sh;
                context.drawImage(tilesImage, 0, sy, sw, sh, dx, dy, sw, sh);

            }
            if (c == cellTypeLeak)
            {
                var sy = 16 * sh;
                context.drawImage(tilesImage, 0, sy, sw, sh, dx, dy, sw, sh);
            }
            else if (c == cellTypeDoorShut)
            {
                var sy = 17 * sh;
                context.drawImage(tilesImage, 0, sy, sw, sh, dx, dy, sw, sh);
            }
            else if (c == cellTypeDoorOpen)
            {
                var sy = 18 * sh;
                context.drawImage(tilesImage, 0, sy, sw, sh, dx, dy, sw, sh);
            }

        }
    }
}

function GetVisualWaterLevel(x, y)
{
    var index = x + y * xSize;
    var w = 0;

    if (equalizeCompartments)
    {
        var floodGroupIndex = cellFloodGroup[index];
        if (floodGroupIndex != noFloodGroup)
        {
            w = floodGroupWaterLevel[floodGroupIndex];
        }
    }
    else
    {
        w = cellWaterLevel[index];
    }
    return Math.min(w, 1.0);
}

function RemoveInvalidDoors()
{
    // Our construction system makes some door placement invalid.
    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            if (IsDoor(cellType[x + y * xSize]))
            {
                var invalid = false;
                if (y - 1 >= 0 && cellType[x + (y - 1) * xSize] != cellTypeEmpty)
                {
                    invalid = true;
                }
                else if (y + 1 < ySize && cellType[x + (y + 1) * xSize] != cellTypeEmpty)
                {
                    invalid = true;
                }

                if (invalid)
                {
                    cellType[x + y * xSize] = cellTypeCorridor;
                }

            }
        }
    }
}

function GetPressureColor(w)
{
    var r, g, b;
    if (w > 3.0)
    {
        var l = Math.min(w - 3.0, 1.0);
        // Yellow to red.
        r = 1;
        g = 1 - l;
        b = 0;
    }
    else if (w > 2.0)
    {
        var l = w - 2.0;
        // Cyan to yellow.
        r = l;
        g = 1;
        b = 1 - l;
    }
    else  if (w > 1.0)
    {
        var l = w - 1.0;
        // Blue to cyan.
        r = 0;
        g = l;
        b = 1;
    }
    else
    {
        // Black to blue.
        r = 0;
        g = 0;
        b = w;
    }
    return "rgba(" + Math.floor(r * 255) + "," + Math.floor(g * 255) + "," + Math.floor(b * 255) + ", 0.5)";
}

function RenderCellOverlay(x, y, offset, width, damagedFillStyle)
{
    var w = GetVisualWaterLevel(x, y);
    if (w > 0)
    {
        if (showPressure)
        {
            var pressure = cellWaterLevel[x + y * xSize];
            context.fillStyle = GetPressureColor(pressure);
        }
        else
        {
            context.fillStyle = "rgba(0, 100, 255, 0.5)";
        }
        var height = w * cellSize;
        context.fillRect(x * cellSize + offset, (y + 1) * cellSize - height, width, height);
    }

    var compartmentIndex = cellCompartment[x + y * xSize];
    if (compartmentIndex != noCompartment)
    {
        if (compartmentStatus[compartmentIndex] == compartmentStatusLeaks)
        {
            context.fillStyle = damagedFillStyle;
            context.fillRect(x * cellSize + offset, y * cellSize, width, cellSize);
        }
    }

}

function RenderCellsOverlays()
{
    context.fillStyle = "rgba(0, 100, 255, 0.5)";
    context.globalCompositeOperation = "source-atop";

    var opacity = (Math.sin(time * damageFlashFrequency) * 0.5 + 0.5) * damageFlashAmount;
    var damagedFillStyle = "rgba(255, 0, 0, " + opacity + ")";

    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            var c = cellType[x + y * xSize];
            if (IsDoor(c))
            {
                // Doors render in a special way since they display the water level from the two adjacent cells.
                if (x - 1 > 0)
                {
                    RenderCellOverlay(x - 1, y, cellSize, doorWidth, damagedFillStyle);
                }
                if (x + 1 < xSize)
                {
                    RenderCellOverlay(x + 1, y, -doorWidth, doorWidth, damagedFillStyle);
                }
            }
            else
            {
                RenderCellOverlay(x, y, 0, cellSize, damagedFillStyle);
            }
        }
    }

    context.globalCompositeOperation = "destination-over";

    // Render the global water level.
    var waterHeight = globalWaterLevel * cellSize;
    context.fillStyle = waterGradient;
    context.fillRect(0, ySize * cellSize - waterHeight, xSize * cellSize, waterHeight);

    // Render the sky.
    context.fillStyle = skyGradient;
    context.fillRect(0, 0, xSize * cellSize, ySize * cellSize);

    context.globalCompositeOperation = "source-over";

}

function Render()
{
    context.clearRect(0, 0, canvas.width, canvas.height);
    RenderCells();
    RenderCellsOverlays();
}

function AssignFloodGroup(x, y, floodGroupIndex)
{
    if (cellFloodGroup[x + y * xSize] != noFloodGroup)
    {
        return 0.0;
    }

    var area = 1.0;
    cellFloodGroup[x + y * xSize] = floodGroupIndex;

    if (IsInside(x - 1, y) && !IsDoor(cellType[(x - 1) + y * xSize]))
    {
        area += AssignFloodGroup(x - 1, y, floodGroupIndex);
    }
    if (IsInside(x + 1, y) && !IsDoor(cellType[(x + 1) + y * xSize]))
    {
        area += AssignFloodGroup(x + 1, y, floodGroupIndex);
    }

    return area;
}

function AssignCompartment(x, y, compartmentIndex)
{
    if (cellCompartment[x + y * xSize] != noCompartment)
    {
        return 0.0;
    }

    var area = 1.0;
    cellCompartment[x + y * xSize] = compartmentIndex;

    if (IsInside(x - 1, y) && cellType[(x - 1) + y * xSize] != cellTypeDoorShut)
    {
        area += AssignCompartment(x - 1, y, compartmentIndex);
    }
    if (IsInside(x + 1, y) && cellType[(x + 1) + y * xSize] != cellTypeDoorShut)
    {
        area += AssignCompartment(x + 1, y, compartmentIndex);
    }
    if (IsInside(x, y - 1))
    {
        area += AssignCompartment(x, y - 1, compartmentIndex);
    }
    if (IsInside(x, y + 1))
    {
        area += AssignCompartment(x, y + 1, compartmentIndex);
    }

    return area;
}

function BuildFloodGroups()
{

    for (var index = 0; index < xSize * ySize; ++index)
    {
        cellFloodGroup[index] = noFloodGroup;
    }

    floodGroupArea = new Array();
    var numFloodGroups = 0;
    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            if (IsInside(x, y) && !IsDoor(cellType[x,y]))
            {
                var area = AssignFloodGroup(x, y, numFloodGroups);
                if (area > 0)
                {
                    ++numFloodGroups;
                    floodGroupArea.push(area);
                }
            }
        }
    }

    floodGroupWaterLevel = new Array(numFloodGroups);
    for (var i = 0; i < numFloodGroups; ++i)
    {
        floodGroupWaterLevel[i] = 0;
    }

}

function BuildCompartments()
{

    for (var index = 0; index < xSize * ySize; ++index)
    {
        cellCompartment[index] = noCompartment;
    }

    var numCompartments = 0;
    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            if (IsInside(x, y) && !IsDoor(cellType[x,y]))
            {
                var area = AssignCompartment(x, y, numCompartments);
                if (area > 0)
                {
                    ++numCompartments;
                }
            }
        }
    }

    compartmentStatus = new Array(numCompartments);
    for (var i = 0; i < numCompartments; ++i)
    {
        compartmentStatus[i] = compartmentStatusNoLeaks;
    }

}

function ComputeFloodGroupLevels()
{
    for (var index = 0; index < floodGroupWaterLevel.length; ++index)
    {
        floodGroupWaterLevel[index] = 0.0;
    }
    for (var index = 0; index < xSize * ySize; ++index)
    {
        if (cellFloodGroup[index] != noFloodGroup)
        {
            var floodGroupIndex = cellFloodGroup[index];
            // Averave is logically better, but max gives fewer artifacts.
            //floodGroupWaterLevel[floodGroupIndex] += cellWaterLevel[index];
            floodGroupWaterLevel[floodGroupIndex] = Math.max(floodGroupWaterLevel[floodGroupIndex], cellWaterLevel[index]);
        }
    }
    /*
    for (var index = 0; index < floodGroupWaterLevel.length; ++index)
    {
        floodGroupWaterLevel[index] /= floodGroupArea[index];
    }
    */
}

function OutsidePressure(y)
{
    var depth = y - (ySize - globalWaterLevel);
    if (depth > 0.0)
    {
        var outsidePressure = 1.0 + depth * maxCompression;
        return outsidePressure;
    }
    return -1.0;
}

function AddLeaksAndDraining(deltaTime)
{

    for (var index = 0; index < compartmentStatus.length; ++index)
    {
        compartmentStatus[index] = compartmentStatusNoLeaks;
    }

    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            var index = x + y * xSize;
            if (cellType[index] == cellTypeLeak)
            {
                var outsidePressure = OutsidePressure(y);
                var delta = outsidePressure - cellWaterLevel[index];

                if (delta > 0)
                {
                    cellWaterLevel[index] += Math.min(delta, deltaTime * leakSpeed);
                }
                else
                {
                    cellWaterLevel[index] -= Math.min(-delta, deltaTime * leakSpeed);
                }

                var compartmentIndex = cellCompartment[index];
                compartmentStatus[compartmentIndex] = compartmentStatusLeaks;
            }
        }
    }

    var drainFlow = drainRate * deltaTime;

    for (var index = 0; index < xSize * ySize; ++index)
    {
        var compartmentIndex = cellCompartment[index];
        if (compartmentIndex != noCompartment)
        {
            if (compartmentStatus[compartmentIndex] == compartmentStatusNoLeaks)
            {
                var remainingWaterLevel = cellWaterLevel[index];
                cellWaterLevel[index] = Math.max(remainingWaterLevel - drainFlow, 0.0);
            }
        }
    }

}

function IsDoor(cellType)
{
    return cellType == cellTypeDoorShut || cellType == cellTypeDoorOpen;
}

function IsInside(x, y)
{
    return x >= 0 && y >= 0 && x < xSize && y < ySize && cellType[x + y * xSize] != cellTypeEmpty;
}

function IsPassable(x, y)
{
    return IsInside(x, y) && cellType[x + y * xSize] != cellTypeDoorShut;
}

function Clamp(x, min, max)
{
    return Math.max(min, Math.min(x, max))
}

function FloodSimUpdate()
{
    if (!loaded)
    {
        return;
    }

    var deltaTime = interval;
    time += deltaTime;

    AddLeaksAndDraining(deltaTime);
    Step(deltaTime);
    ComputeFloodGroupLevels();
    Render();
}

function FloodSimOnContextMenu(event)
{
    // Block the context menu so we can handle right click in OnMouseDown.
    event.preventDefault();
    return false;
}

function FloodSimOnMouseDown(event)
{

    // From: http://www.quirksmode.org/js/events_properties.html
    var rightclick;
    if (event.which)
    {
        rightClick = (event.which == 3);
    }
    else if (event.button)
    {
        rightClick = (event.button == 2);
    }

    var rect = canvas.getBoundingClientRect();
    var x = Math.floor((event.clientX - rect.left) / cellSize);
    var y = Math.floor((event.clientY - rect.top)  / cellSize);

    var rebuild = false;
    var rebuildCompartments = false;

    if (x >= 0 && y >= 0 && x < xSize && y < ySize)
    {
        var index = x + y * xSize;

        if (controlPressed || rightClick)
        {
            // Erase mode.
            if (cellType[index] == cellTypeCorridor)
            {
                cellType[index] = cellTypeEmpty;
                rebuild = true;
            }
            else if (cellType[index] == cellTypeDoorShut ||
                     cellType[index] == cellTypeDoorOpen)
            {
                cellType[index] = cellTypeCorridor;
                rebuild = true;
            }
            else if (cellType[index] == cellTypeLeak)
            {
                cellType[index] = cellTypeCorridor;
            }
        }
        else if (interactMode == interactModeBuild)
        {
            // Regular mode.
            if (cellType[index] == cellTypeEmpty)
            {
                cellType[index] = cellTypeCorridor;
                rebuild = true;
            }
            else if (cellType[index] == cellTypeCorridor)
            {
                cellType[index] = cellTypeEmpty;
                rebuild = true;
            }
            else if (cellType[index] == cellTypeDoorShut)
            {
                cellType[index] = cellTypeDoorOpen;
                rebuildCompartments = true;
            }
            else if (cellType[index] == cellTypeDoorOpen)
            {
                cellType[index] = cellTypeDoorShut;
                rebuildCompartments = true;
            }
            else if (cellType[index] == cellTypeLeak)
            {
                cellType[index] = cellTypeCorridor;
            }
        }
        else if (interactMode == interactModePlaceLeak)
        {
            cellType[index] = cellTypeLeak;
            rebuild = true;
        }
        else if (interactMode == interactModePlaceDoor)
        {
            cellType[index] = cellTypeDoorShut;
            rebuild = true;
        }

    }

    if (rebuild)
    {
        RemoveInvalidDoors();
        BuildFloodGroups();
        rebuildCompartments = true;
    }

    if (rebuildCompartments)
    {
        BuildCompartments();
    }

}

function Step(deltaTime)
{

    for (var index = 0; index < xSize * ySize; ++index)
    {
        cellDelta[index] = 0.0;
    }

    //
    // Consider two vertically stacked cells with "pressure" A and B (we also label these cells as A and B for description)
    // A is the cell we're computing the flow for and B is it's neighbor.
    //
    //      +---+
    //      | A |
    //      +---+
    //      | B |
    //      +---+
    //
    // The total volume of water stored between these two cells is: sum = A + B.
    // We will apply rules to rebalance the distribution of water to equalize the pressure.
    //
    // There are 3 cases to consider:
    //      - All of the water can fit in cell B
    //      - All of the water can fit in cell A and B without overfilling
    //      - Both A and B will be overfilled.
    //
    // We're going to compute new pressure values A' and B' to equalize the pressure.
    //
    // To allow for pressure to propagate through the entire grid, we allow the lower cell to have slightly higher pressure
    // than the upper cell, so that after equalization the pressure should be:
    //
    //      B' = A' + maxCompression
    //
    // To preserve the volume of water during the equalization, the following must hold:
    //
    //      A + B = A' + B'
    //
    // We can use these two equations to solve for A' in terms of our known quantities:
    //
    //      A + B = A' + A' + maxCompression
    //      A' = (A + B - maxCompression) / 2
    //
    // By solving these two equations we compute how much water must flow from A to B to achieve the equalization:
    //
    //      flow = A - A'
    //           = A - (A + B - maxCompression) / 2
    //

    for (var y = 0; y < ySize; ++y)
    {
        for (var x = 0; x < xSize; ++x)
        {
            if (!IsPassable(x, y))
            {
                continue;
            }

            var index = x + y * xSize;
            var remainingWaterLevel = cellWaterLevel[index];

            var maxVerticalFlow = flowRate * deltaTime;
            var maxSideFlow;

            if (cellType[index] == cellTypeDoorOpen)
            {
                maxSideFlow = bulkheadFlowRate * deltaTime;
            }
            else
            {
                maxSideFlow = flowRate * deltaTime;
            }

            // Equalize with the side neighbors. Doing this before the up and down directions leads to a more
            // stable result.

            var flowE = 0.0;
            var flowW = 0.0;

            var average = cellWaterLevel[index];
            var numNeighbors = 0;

            if (IsPassable(x - 1, y))
            {
               average += cellWaterLevel[(x - 1) + y * xSize];
                ++numNeighbors;

                flowW = (remainingWaterLevel - cellWaterLevel[(x - 1) + y * xSize]) * 0.25;
                flowW = Clamp(flowW, 0, maxSideFlow);
            }
            if (IsPassable(x + 1, y))
            {
                average += cellWaterLevel[(x + 1) + y * xSize];
                ++numNeighbors;

                flowE = (remainingWaterLevel - cellWaterLevel[(x + 1) + y * xSize]) * 0.25;
                flowE = Clamp(flowE, 0, maxSideFlow);
            }

            average /= numNeighbors + 1;

            var maxFlow = Math.max(remainingWaterLevel - average, 0);
            var totalFlow = flowW + flowE;
            var restrictedFlow = totalFlow;//Math.min(totalFlow, maxFlow);

            // Rescale the flow so we don't exceed the restricted flow.

            if (flowW > 0)
            {
                flowW = flowW * restrictedFlow / totalFlow;
                cellDelta[(x - 1) + y * xSize] += flowW;
            }
            if (flowE > 0)
            {
                flowE = flowE * restrictedFlow / totalFlow;
                cellDelta[(x + 1) + y * xSize] += flowE;
            }
            cellDelta[index] -= restrictedFlow;
            remainingWaterLevel -= restrictedFlow;

            // Cell below.
            if (IsPassable(x, y + 1))
            {
                var index2 = x + (y + 1) * xSize;
                var sum = remainingWaterLevel + cellWaterLevel[index2];
                var flow;
                if (sum <= 1.0)
                {
                    // All of the water can fit in a single cell, so it will all flow to the bottom.
                    flow = remainingWaterLevel;
                }
                else if (sum <= 2.0 + maxCompression)
                {
                    // Bottom cell will fill to capacity and whatever is left over will go in the top cell.
                    // We allow the bottom cell to be overfilled by an amount that's proportional to what's
                    // left in the top cell:
                    //      A' = sum - B'
                    //      B' = 1 + A' * maxCompression
                    var newWaterLevel = (sum - 1.0) / (1.0 + maxCompression);
                    flow = remainingWaterLevel - newWaterLevel;
                }
                else
                {
                    // Both cells are under pressure, so equalize:
                    //      A + B = A' + B'
                    //      B' = A' + maxCompression
                    var newWaterLevel = (remainingWaterLevel + cellWaterLevel[index2] - maxCompression) * 0.5;
                    flow = remainingWaterLevel - newWaterLevel;
                }
                flow = Clamp(flow, 0, maxVerticalFlow);

                cellDelta[index] -= flow;
                cellDelta[index2] += flow;

                remainingWaterLevel -= flow;
            }

            // Cell above.
            if (IsPassable(x, y - 1))
            {
                var index2 = x + (y - 1) * xSize;
                var sum = remainingWaterLevel + cellWaterLevel[index2];
                var flow;

                if (sum <= 1.0)
                {
                    // All of the water can fit in a single cell, so it will all flow to the bottom, which
                    // means our flow out of this cell is negative (i.e. we don't do it).
                    flow = 0.0;
                }
                else if (sum <= 2.0 + maxCompression)
                {
                    // Bottom cell will fill to capacity, and whatever is left over will go in the top cell.
                    // We allow the bottom cell to be overfulled by an amount that's proportional to what's
                    // left in the top cell:
                    //      A' = 1 + B' * maxCompression
                    //      B' = sum - A'
                    var newWaterLevel = (1.0 + maxCompression * sum) / (1.0 + maxCompression);
                    flow = remainingWaterLevel - newWaterLevel;
                }
                else
                {
                    // Both cells are under pressure, so equalize.
                    //      A + B = A' + B'
                    //      A' = B' + maxCompression
                    var newWaterLevel = (cellWaterLevel[index] + cellWaterLevel[index2] + maxCompression) * 0.5;
                    flow = remainingWaterLevel - newWaterLevel;
                }
                flow = Clamp(flow, 0, maxVerticalFlow);

                cellDelta[index] -= flow;
                cellDelta[index2] += flow;

                remainingWaterLevel -= flow;
            }

        }
    }

    for (var index = 0; index < xSize * ySize; ++index)
    {
        cellWaterLevel[index] += cellDelta[index];
    }

}

function FloodSimOnKeyDown(event)
{
    if (event.keyCode == 17)
    {
        controlPressed = true;
    }
}

function FloodSimOnKeyUp(event)
{
    if (event.keyCode == 17)
    {
        controlPressed = false;
    }
}

function SyncToControlsForm()
{
    document.getElementById("flood_sim_show_pressure").checked = showPressure;

    if (interactMode == interactModeBuild)
    {
        document.getElementById("flood_sim_build").checked = true;
    }
    else if (interactMode == interactModePlaceDoor)
    {
        document.getElementById("flood_sim_place_door").checked = true;
    }
    else if (interactMode == interactModePlaceLeak)
    {
        document.getElementById("flood_sim_place_leak").checked = true;
    }

    var globalWaterLevelSlider = document.getElementById("flood_sim_global_water_level");
    globalWaterLevelSlider.value = globalWaterLevel * (globalWaterLevelSlider.max - globalWaterLevelSlider.min) / ySize + Number(globalWaterLevelSlider.min);

}

function SyncFromControlsForm()
{
    showPressure = document.getElementById("flood_sim_show_pressure").checked;

    if (document.getElementById("flood_sim_place_door").checked)
    {
        interactMode = interactModePlaceDoor;
    }
    else if (document.getElementById("flood_sim_place_leak").checked)
    {
        interactMode = interactModePlaceLeak;
    }
    else
    {
        // Interact mode.
        interactMode = interactModeBuild;
    }

    var globalWaterLevelSlider = document.getElementById("flood_sim_global_water_level");
    globalWaterLevel = ySize * (globalWaterLevelSlider.value - globalWaterLevelSlider.min) / (globalWaterLevelSlider.max - globalWaterLevelSlider.min);

    CreateGradients();

}

function OnControlsFormChange(event)
{
    SyncFromControlsForm();
}

function AddFormChangeMethod(form, tag, method)
{
    var inputs = form.getElementsByTagName(tag);
    for (var i = 0; i < inputs.length; i++)
    {
        inputs[i].addEventListener("change", method);
        inputs[i].addEventListener("input", method);
    }
}

function ApplyLayout(layout)
{
    for (var index = 0; index < xSize * ySize && index < layout.length; ++index)
    {
        if (layout.charAt(index) == '.')
        {
            cellType[index] = cellTypeEmpty;
        }
        else if (layout.charAt(index) == 'X')
        {
            cellType[index] = cellTypeCorridor;
        }
        else if (layout.charAt(index) == 'D')
        {
            cellType[index] = cellTypeDoorShut;
        }
        else if (layout.charAt(index) == 'F')
        {
          cellType[index] = cellTypeCorridor;
          cellWaterLevel[index] = 1.0;
        }
        else if (layout.charAt(index) == 'L')
        {
            cellType[index] = cellTypeLeak;
        }
    }
}

function CreateGradients()
{
    var waterHeight = globalWaterLevel * cellSize;
    skyGradient = context.createLinearGradient(0, -waterHeight, 0, canvas.height - waterHeight);
    skyGradient.addColorStop(0, '#004CB3');
    skyGradient.addColorStop(1, '#8ED6FF');

    waterGradient = context.createLinearGradient(0, ySize * cellSize - waterHeight, 0, ySize * cellSize - waterHeight + ySize * cellSize);
    waterGradient.addColorStop(0, 'rgba(20, 80, 130, 1)');
    waterGradient.addColorStop(1, 'rgba(0, 0, 0, 1)');
}

function FloodSimInitialize()
{
    canvas = document.getElementById("flood_sim_canvas");
    context = canvas.getContext("2d");

    canvas.tabIndex    = 1000; // Force the canvas to get key inputs
    canvas.addEventListener("mousedown", FloodSimOnMouseDown);
    canvas.addEventListener("contextmenu", FloodSimOnContextMenu);
    canvas.addEventListener("keydown",   FloodSimOnKeyDown);
    canvas.addEventListener("keyup",     FloodSimOnKeyUp);

    // Add event handlers for all of our form elements.
    var form = document.getElementById("flood_sim_controls");
    AddFormChangeMethod(form, "input", OnControlsFormChange);
    AddFormChangeMethod(form, "radio", OnControlsFormChange);

    SyncToControlsForm();

    for (var index = 0; index < xSize * ySize; ++index)
    {
        cellType[index] = cellTypeEmpty;
        cellWaterLevel[index] = 0;
    }

    // Initial layout.

    var layout = "\
...............\
.....XXXXX.....\
.....X......X..\
..X..X......X..\
..X..XXXXXXXX..\
..X.......X....\
..XXXXXDXXLX...\
..............."
    ApplyLayout(layout);

    BuildFloodGroups();
    BuildCompartments();

    tilesImage = new Image();
    tilesImage.src = "img/flood_sim_tiles.png";
    tilesImage.onload = function() { loaded = true; };

    CreateGradients();

    setInterval(FloodSimUpdate, interval * 1000.0);
}


text:
FieldGraphicItem::FieldGraphicItem()
{
}

QRectF FieldGraphicItem::boundingRect() const
{
    return QRectF(-3, -3, 3, 3);
}

void FieldGraphicItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;
    QBrush mybrush;

    SettingCenter* sc = SettingCenter::singleton();

    pen.setColor(Qt::black);
    pen.setWidth(5);
    mybrush.setColor(Qt::darkGray);
    mybrush.setStyle(Qt::SolidPattern);

    painter->setPen(pen);
    painter->setBrush(mybrush);
    painter->drawRect(sc->getSettingValue("field/left_top_x").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/left_top_y").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/width").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/height").toDouble()/SCENE_SCALE);

    pen.setColor(Qt::black);
    pen.setWidth(3);
    mybrush.setColor(Qt::darkGray);
    mybrush.setStyle(Qt::NoBrush);

    painter->setPen(pen);
    painter->setBrush(mybrush);
    painter->drawRect(sc->getSettingValue("field/abovepen_left_top_x").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovepen_left_top_y").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovepen_width").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovepen_height").toDouble()/SCENE_SCALE);

    pen.setColor(Qt::black);
    pen.setWidth(3);
    mybrush.setColor(Qt::darkGray);
    mybrush.setStyle(Qt::NoBrush);

    painter->setPen(pen);
    painter->setBrush(mybrush);
    painter->drawRect(sc->getSettingValue("field/lowpen_left_top_x").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowpen_left_top_y").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowpen_width").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowpen_height").toDouble()/SCENE_SCALE);

    pen.setColor(Qt::black);
    pen.setWidth(3);
    mybrush.setColor(Qt::darkGray);
    mybrush.setStyle(Qt::NoBrush);

    painter->setPen(pen);
    painter->setBrush(mybrush);
    painter->drawRect(sc->getSettingValue("field/abovegoal_left_top_x").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovegoal_left_top_y").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovegoal_width").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/abovegoal_height").toDouble()/SCENE_SCALE);

    pen.setColor(Qt::black);
    pen.setWidth(3);
    mybrush.setColor(Qt::darkGray);
    mybrush.setStyle(Qt::NoBrush);

    painter->setPen(pen);
    painter->setBrush(mybrush);
    painter->drawRect(sc->getSettingValue("field/lowgoal_left_top_x").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowgoal_left_top_y").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowgoal_width").toDouble()/SCENE_SCALE,
                      sc->getSettingValue("field/lowgoal_height").toDouble()/SCENE_SCALE);

    pen.setWidth(1);
    painter->drawLine(0,0,-50,0);
    painter->drawLine(0,0,0,50);
}


text:
<?php declare(strict_types=1);
namespace Imbo\EventListener\Initializer;

use Imagick;
use Imbo\EventListener\Imagick as ImagickEventListener;
use Imbo\EventListener\Initializer\Imagick as ImagickInitializer;
use Imbo\Image\Transformation\Border;
use PHPUnit\Framework\TestCase;

/**
 * @coversDefaultClass Imbo\EventListener\Initializer\Imagick
 */
class ImagickTest extends TestCase
{
    /**
     * @covers ::initialize
     */
    public function testInjectsImagickIntoEventListeners(): void
    {
        $imagick = $this->createMock(Imagick::class);

        $listener = $this->createMock(ImagickEventListener::class);
        $listener
            ->expects($this->once())
            ->method('setImagick')
            ->with($imagick);

        (new ImagickInitializer($imagick))->initialize($listener);
    }

    /**
     * @covers ::__construct
     * @covers ::initialize
     */
    public function testCanCreateAnImagickInstanceByItself(): void
    {
        $listener = $this->createMock(Border::class);
        $listener
            ->expects($this->once())
            ->method('setImagick')
            ->with($this->isInstanceOf(Imagick::class));

        (new ImagickInitializer())->initialize($listener);
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TowerSQL.Functions {

    public static class SqlSystem {

        #region Default System Functions

        public static string AppName() {
            throw new NotImplementedException();
        }

        public static string Case() {
            throw new NotImplementedException();
        }

        public static string Cast() {
            throw new NotImplementedException();
        }

        public static string Convert() {
            throw new NotImplementedException();
        }

        public static string Coalesce() {
            throw new NotImplementedException();
        }

        public static string CollationProperty() {
            throw new NotImplementedException();
        }

        public static string ColumnsUpdated() {
            throw new NotImplementedException();
        }

        public static string CurrentTimeStamp() {
            return DateTime.CurrentTimeStamp;
        }

        public static string CurrentUser() {
            return Security.CurrentUser();
        }

        public static string DataLength() {
            throw new NotImplementedException();
        }

        public const string Error = "@@ERROR";

        public static string ErrorLine() {
            throw new NotImplementedException();
        }

        public static string ErrorMessage() {
            throw new NotImplementedException();
        }

        public static string ErrorNumber() {
            throw new NotImplementedException();
        }

        public static string ErrorProcedure() {
            throw new NotImplementedException();
        }

        public static string ErrorSeverity() {
            throw new NotImplementedException();
        }

        public static string ErrorState() {
            throw new NotImplementedException();
        }

        public static string HelpCollations() {
            // fn_helpcollations
            throw new NotImplementedException();
        }

        public static string ServerSharedDrivers() {
            // fn_servershareddrives
            throw new NotImplementedException();
        }

        // implemented below
        //public static string VirtualFileStats() {
        //}

        public static string FormatMessage() {
            throw new NotImplementedException();
        }

        public static string GetAnsiNull() {
            throw new NotImplementedException();
        }

        public static string HostId() {
            throw new NotImplementedException();
        }

        public static string HostName() {
            throw new NotImplementedException();
        }

        public static string IdentCurrent() {
            throw new NotImplementedException();
        }

        public static string IdentIncr() {
            throw new NotImplementedException();
        }

        public static string IdentSeed() {
            throw new NotImplementedException();
        }

        // public const string Identity = "@@IDENTITY";

        public static string Identity() {
            throw new NotImplementedException();
        }

        public static string IsDate() {
            return DateTime.IsDate(null);
        }

        public static string IsNull() {
            throw new NotImplementedException();
        }

        public static string IsNumeric() {
            throw new NotImplementedException();
        }

        public static string NewId() {
            throw new NotImplementedException();
        }

        public static string NullIf() {
            throw new NotImplementedException();
        }

        public static string ParseName() {
            throw new NotImplementedException();
        }

        public static string OriginalLogin() {
            return Security.OriginalLogin();
        }

        public const string RowCount = "@@ROWCOUNT";

        public static string RowCountBig() {
            throw new NotImplementedException();
        }

        public static string ScopeIdentity() {
            throw new NotImplementedException();
        }

        public static string ServerProperty() {
            throw new NotImplementedException();
        }

        public static string SessionProperty() {
            throw new NotImplementedException();
        }

        public static string SessionUser() {
            throw new NotImplementedException();
        }

        public static string StatsDate() {
            throw new NotImplementedException();
        }

        public static string DmDbIndexPhysicalStats() {
            // sys.dm_db_index_physical_stats
            throw new NotImplementedException();
        }

        public static string SystemUser() {
            return Security.SystemUser();
        }

        public const string TransactionCount = "@@TRANCOUNT";

        public static string Update() {
            throw new NotImplementedException();
        }

        public static string UserName() {
            return Security.UserName();
        }

        public static string XactState() {
            throw new NotImplementedException();
        }

        #endregion

        #region Statistical System Functions

        public const string Connections = "@@CONNECTIONS";

        public const string CPUBusy = "@@CPU_BUSY";

        public static string VirtualFileStats(string databaseId = null, string fileId = null) {
            return string.Concat("fn_virtualfilestats(", databaseId ?? InternalConstants.Null, fileId ?? InternalConstants.Null, ")");
        }

        public static string VirtualFileStats(int? databaseId = null, int? fileId = null) {
            return string.Concat("fn_virtualfilestats(", databaseId.HasValue ? databaseId.Value.ToString() : InternalConstants.Null, fileId.HasValue ? fileId.Value.ToString() : InternalConstants.Null, ")");
        }

        public const string Idle = "@@IDLE";

        public const string IOBusy = "@@IO_BUSY";

        public const string PacketsReceived = "@@PACK_RECEIVED";

        public const string PacketsSent = "@@PACK_SENT";

        public const string PacketErrors = "@@PACKET_ERRORS";

        public const string TimeTicks = "@@TIMETICKS";

        public const string TotalErrors = "@@TOTAL_ERRORS";

        public const string TotalRead = "@@TOTAL_READ";

        public const string TotalWrite = "@@TOTAL_WRITE";

        #endregion

    }

}


text:
**Tcp.Net** is a lightweight TCP library for .Net based on [SocketAsyncEventArgs](https://github.com/dotnet/corefx/blob/master/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs) supports OS I/O multiplexing queues: **I/O Completion Ports**, **epoll**, **kqueue**, etc.

This prevents excess memory allocations and provides a reliable and convinient way for establishing and accepting connections and for sending and receiving chunks of data using flexible buffers.

## Low-Level API
Pure and lightweight Tcp library based on SocketAsyncEventArgs.

#### [a lot of changes occuried, so all examples are going to be rewritten]

### Opens an endpoint listening for incoming connections
```c#
// Prerequisites:
//  Setup and bind socket
//  Start to listen a socket for incoming connections.

ArgsPool acceptPool = ArgsPool.Create(1);

SocketEx socketEx = new SocketEx(socket);

socketEx.Accepted += (s, e) =>
{
    // The incoming connection was accepted

    // Continue accepting incoming connections
    socketEx.AcceptAsyncEx(acceptPool.GetAutoreleasedArgs());

    SocketEx remoteSocketEx = new SocketEx(e.AcceptSocket);

    // receive or send data using remoteSocketEx (see below)
}

socketEx.AcceptAsyncEx(acceptPool.GetAutoreleasedArgs());
```

### Establish a connection with remote endpoint
```c#
// Prerequisites:
// Setup socket

ArgsPool connectPool = ArgsPool.Create(1);

SocketEx socketEx = new SocketEx(socket);

socketEx.Connected += (s, e) =>
{
    // The outgoing connection was established

    SocketEx remoteSocketEx = new SocketEx(e.ConnectSocket);

    // receive or send data using remoteSocketEx (see below)
}

socketEx.Failed += (s, e) =>
{
    // Attempt to establish a connection failed
}

// Establish a connection with remote endpoint.
socketEx.ConnectAsyncEx(connectPool.GetAutoreleasedArgs().AssignRemoteEndPoint(ipEndPoint));
```

### Handle closing the connection by remote end
```c#
remoteSocketEx.Closed += (s1, e1) =>
{
    // The connection was closed by remote end
}
```

### Handle an failure occurred during the connection
```c#
remoteSocketEx.Failed += (s1, e1) =>
{
    // An error occuried during the connection
    // Use (e1.SocketError) to handle error
}
```

### Receive chunks of data from the connection
```c#
ArgsPool receivePool = ArgsPool.Create(1024);

remoteSocketEx.Received += (s1, e1) =>
{
    // The data was received through the connection
    char[] receivedChars = Encoding.UTF8.GetChars(e1.Buffer, e1.Offset, e1.Length);

    // Receive the next chunk of data from the connection
    connection.ReceiveAsync(
        buffer: receiveBuffer,
        offset: 0,
        length: receiveBuffer.Length,
        args: receivePool.GetAutoreleaseArgs());
}

// Receive the first chunk of data from the connection
remoteSocketEx.ReceiveAsync(
    buffer: receiveBuffer,
    offset: 0,
    length: receiveBuffer.Length,
    args: receivePool.GetAutoreleaseArgs());
```

### Send chunks of data to the connection
```c#
int sendChunkSizeInBytes = 1024;
ArgsPool sendPool = ArgsPool.Create(1024);

remoteSocketEx.Sent += (s1, e1) =>
{
    // The data sent through the connection
    char[] sentChars = Encoding.UTF8.GetChars(e1.Buffer, e1.Offset, e1.Length);

    // Send the next chunk of data through the connection
    int offset = e1.Offset + e1.Length;
    int left = e1.Buffer.Length - offset;
    if (left > 0)
    {
        int length = left < sendChunkSizeInBytes ? left : sendChunkSizeInBytes;

        remoteSocketEx.SendAsync(
            buffer: e1.Buffer,
            offset: offset,
            length: length,
            args: sendPool.GetAutoreleaseArgs());
    }
}

// Send the first chunk of data through the connection
remoteSocketEx.SendAsync(
    buffer: sendBuffer,
    offset: 0,
    length: sendChunkSizeInBytes,
    args: sendPool.GetAutoreleaseArgs());
```

# TODO:

### Solution components:

- [x] Low-Level API - Pure and lightweight Tcp library based on SocketAsyncEventArgs.
- [ ] High-Level API - Designed for simplicity set of features includes async/await wrapper, efficient buffering and pooling support
- [ ] Integration Tests - Demonstrates code examples and abilities.
- [ ] Load Tests - Measures how much the library loads the computer.
- [ ] Client Application - Allows to send and receive a raw data via TCP protocol.


text:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var FaceFeatureExtractor_1 = require("../faceFeatureExtractor/FaceFeatureExtractor");
var FaceLandmark68NetBase_1 = require("./FaceLandmark68NetBase");
var FaceLandmark68Net = /** @class */ (function (_super) {
    tslib_1.__extends(FaceLandmark68Net, _super);
    function FaceLandmark68Net(faceFeatureExtractor) {
        if (faceFeatureExtractor === void 0) { faceFeatureExtractor = new FaceFeatureExtractor_1.FaceFeatureExtractor(); }
        return _super.call(this, 'FaceLandmark68Net', faceFeatureExtractor) || this;
    }
    FaceLandmark68Net.prototype.getDefaultModelName = function () {
        return 'face_landmark_68_model';
    };
    FaceLandmark68Net.prototype.getClassifierChannelsIn = function () {
        return 256;
    };
    return FaceLandmark68Net;
}(FaceLandmark68NetBase_1.FaceLandmark68NetBase));
exports.FaceLandmark68Net = FaceLandmark68Net;
//# sourceMappingURL=FaceLandmark68Net.js.map


text:
#include "config.h"
#include "CDMSessionClearKey.h"

#include "ArrayValue.h"
#include "CryptoAlgorithm.h"
#include "CryptoAlgorithmIdentifier.h"
#include "CryptoAlgorithmParameters.h"
#include "CryptoKeyDataOctetSequence.h"
#include "Dictionary.h"
#include "JSMainThreadExecState.h"
#include "Logging.h"
#include "MediaKeyError.h"
#include "TextEncoding.h"
#include "UUID.h"
#include <runtime/JSGlobalObject.h>
#include <runtime/JSLock.h>
#include <runtime/JSONObject.h>
#include <runtime/VM.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/text/Base64.h>

#if ENABLE(ENCRYPTED_MEDIA_V2)

using namespace JSC;

namespace WebCore {

static VM& clearKeyVM()
{
    static NeverDestroyed<RefPtr<VM>> vm;
    if (!vm.get())
        vm.get() = VM::create();

    return *vm.get();
}

CDMSessionClearKey::CDMSessionClearKey(CDMSessionClient* client)
    : m_client(client)
    , m_sessionId(createCanonicalUUIDString())
{
}

CDMSessionClearKey::~CDMSessionClearKey()
{
}

RefPtr<Uint8Array> CDMSessionClearKey::generateKeyRequest(const String& mimeType, Uint8Array* initData, String& destinationURL, unsigned short& errorCode, uint32_t& systemCode)
{
    UNUSED_PARAM(mimeType);
    UNUSED_PARAM(destinationURL);
    UNUSED_PARAM(systemCode);

    if (!initData) {
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
        return nullptr;
    }
    m_initData = initData;

    bool sawError = false;
    String keyID = UTF8Encoding().decode(reinterpret_cast_ptr<char*>(m_initData->baseAddress()), m_initData->byteLength(), true, sawError);
    if (sawError) {
        errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
        return nullptr;
    }

    return initData;
}

void CDMSessionClearKey::releaseKeys()
{
    m_cachedKeys.clear();
}

bool CDMSessionClearKey::update(Uint8Array* rawKeysData, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, uint32_t& systemCode)
{
    UNUSED_PARAM(nextMessage);
    UNUSED_PARAM(systemCode);
    ASSERT(rawKeysData);

    do {
        String rawKeysString = String::fromUTF8(rawKeysData->data(), rawKeysData->length());
        if (rawKeysString.isEmpty())  {
            LOG(Media, "CDMSessionClearKey::update(%p) - failed: empty message", this);
            continue;
        }

        VM& vm = clearKeyVM();
        JSLockHolder lock(vm);
        JSGlobalObject* globalObject = JSGlobalObject::create(vm, JSGlobalObject::createStructure(vm, jsNull()));
        ExecState* exec = globalObject->globalExec();

        JSLockHolder locker(clearKeyVM());
        JSValue keysDataObject = JSONParse(exec, rawKeysString);
        if (exec->hadException() || !keysDataObject) {
            LOG(Media, "CDMSessionClearKey::update(%p) - failed: invalid JSON", this);
            break;
        }
        Dictionary keysDataDictionary(exec, keysDataObject);
        ArrayValue keysArray;
        size_t length;
        if (!keysDataDictionary.get("keys", keysArray) || keysArray.isUndefinedOrNull() || !keysArray.length(length) || !length) {
            LOG(Media, "CDMSessionClearKey::update(%p) - failed: keys array missing or empty", this);
            break;
        }

        bool foundValidKey = false;
        for (size_t i = 0; i < length; ++i) {
            Dictionary keyDictionary;
            if (!keysArray.get(i, keyDictionary) || keyDictionary.isUndefinedOrNull()) {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: null keyDictionary", this);
                continue;
            }

            String algorithm;
            if (!keyDictionary.get("alg", algorithm) || !equalLettersIgnoringASCIICase(algorithm, "a128kw")) {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: algorithm unsupported", this);
                continue;
            }

            String keyType;
            if (!keyDictionary.get("kty", keyType) || !equalLettersIgnoringASCIICase(keyType, "oct")) {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: keyType unsupported", this);
                continue;
            }

            String keyId;
            if (!keyDictionary.get("kid", keyId) || keyId.isEmpty()) {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: keyId missing or empty", this);
                continue;
            }

            String rawKeyData;
            if (!keyDictionary.get("k", rawKeyData) || rawKeyData.isEmpty())  {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: key missing or empty", this);
                continue;
            }

            Vector<uint8_t> keyData;
            if (!base64Decode(rawKeyData, keyData) ||  keyData.isEmpty()) {
                LOG(Media, "CDMSessionClearKey::update(%p) - failed: unable to base64 decode key", this);
                continue;
            }

            m_cachedKeys.set(keyId, WTFMove(keyData));
            foundValidKey = true;
        }

        if (foundValidKey)
            return true;

    } while (false);

    errorCode = MediaKeyError::MEDIA_KEYERR_CLIENT;
    return false;
}

RefPtr<ArrayBuffer> CDMSessionClearKey::cachedKeyForKeyID(const String& keyId) const
{
    if (!m_cachedKeys.contains(keyId))
        return nullptr;

    auto keyData = m_cachedKeys.get(keyId);
    RefPtr<Uint8Array> keyDataArray = Uint8Array::create(keyData.data(), keyData.size());
    return keyDataArray->buffer();
}

}

#endif