{"size": 2129, "ext": "js", "max_stars_repo_path": "src/ui/resources/createResourcesPack.js", "max_stars_repo_name": "Mati365/neural-cars", "max_stars_repo_stars_event_min_datetime": "2018-11-18T11:06:24.000Z", "max_stars_repo_stars_event_max_datetime": "2021-05-29T19:34:13.000Z", "max_issues_repo_path": "src/ui/resources/createResourcesPack.js", "max_issues_repo_name": "Mati365/neural-cars", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "src/ui/resources/createResourcesPack.js", "max_forks_repo_name": "Mati365/neural-cars", "max_forks_repo_forks_event_min_datetime": "2019-08-08T10:16:00.000Z", "max_forks_repo_forks_event_max_datetime": "2019-08-08T10:16:00.000Z"}
{"max_stars_count": 21, "max_issues_count": null, "max_forks_count": 1, "avg_line_length": 21.7244897959, "max_line_length": 87, "alphanum_fraction": 0.4964772194}
import * as R from 'ramda';
import {pairs, of} from 'rxjs';
import {scan, flatMap} from 'rxjs/operators';

export const DEFAULT_LOADERS = [
  // image loader
  {
    test: R.test(/\.(png|jpe?g)$/),
    loader: path => new Promise(
      (resolve, reject) => {
        const img = new Image;
        img.src = path;
        img.onload = () => resolve(img);
        img.onerror = e => reject(e);
      },
    ),
  },
];

/**
 * Load resources from path
 *
 * @param {Loader[]}  loaders
 * @param {String}    path
 *
 * @returns {Resource}
 */
const loadResource = loaders => R.converge(
  (loader, path) => {
    if (R.isNil(loader))
      throw new Error('Loader not found!');

    return loader.loader(path);
  },
  [
    // find loader matching test
    path => R.find(
      ({test}) => test(path),
      loaders,
    ),

    // return identity, path to apply if loader found
    R.identity,
  ],
);

/**
 * Load resources from path
 *
 * @param {Loader[]}  loaders
 * @param {String[]}  resources
 *
 * @returns {ResourcePack}
 */
export const createLoadersResourcesPack = R.curry(
  (loaders, resources) => {
    const packLoader = loadResource(loaders);
    const totalResources = R.keys(resources).length;

    if (!totalResources) {
      return of({
        resources: {},
        percentage: 1,
      });
    }

    return (
      pairs(resources)
        .pipe(
          // loads in parallel
          // see: https://stackoverflow.com/a/49701944
          flatMap(
            ([key, path]) => new Promise(
              (resolve, reject) => (
                packLoader(path)
                  .then(loaded => resolve([key, loaded]))
                  .catch(reject)
              ),
            ),
          ),
          scan(
            (acc, [key, value]) => ({
              ...acc,
              percentage: ((R.keys(acc?.resources || {}).length + 1) / totalResources),
              resources: {
                ...acc?.resources,
                [key]: value,
              },
            }),
            {},
          ),
        )
    );
  },
);

export default createLoadersResourcesPack(DEFAULT_LOADERS);
