text:
Q: spectrum analyzer of wave files with numpy.rfft I'm writing a script to process a wave file in Python and display a spectrum analyzer, just for nice visualization of audio files. After some reading of the doc and forums I assumed I needed to use rfft.
I'm processing samples of 2048 values, creating 1024 bands in output of rfft. The thing is that for my needs I would need to reduce the number of bands dramatically to 12 bands (1 octave). Since I'm processing audio files and have a limited number of bands I wonder if there is a smart way to group frequencies so that 90% of songs look nice with low-pitched beats  on the very left and high-pitched voices/shouts/notes on the very right.
With this preliminary code below I have more bands that what I need but also most peaks are concentrated in low frenquencies with most songs, except a test range from 20 to 20k. With this range I also realized that the higher the pitch is, the lower the amplitude is.
def fft(self, sample_range):
    # sample_range is a sample of 2048 ints read from the self.file wave file
    fft_data = abs(numpy.fft.rfft(sample_range)) # real fft gives samplewidth/2 bands
    fft_freq = numpy.fft.rfftfreq(len(sample_range))
    freq_hz = [abs(fft_freq[i])*self.file.getframerate() for i, fft in enumerate(fft_data)]

    print len(zip(freq_hz, fft_data)), len(freq_hz), len(fft_data), zip(freq_hz, fft_data)

Here is the print output for the first sample of the rampe (~20Hz):
1025 1025 1025 [(0.0, 1850501.0), (21.533203125, 2779524.1730200453), (43.06640625, 15469093.29481476), ... (22028.466796875, 3538.1225240980043), (22050.0, 3553.0)]

So my questions are:

*

*Am I doing something that I shouldn't in the code hereabove? =)

*What units spectrum analyzers in most music players represent usually and what are the ranges? Should I convert amplitudes into dB?

*Is there a simple way to reduce the number of bands to 12? I guess the bandwidth is exponential with the pitch? I would say that I need to manually implement this exponential sum.
EDIT: I'm now summing fft frequencies using a reference log-scale that I generate for an arbitrary number of bands with:
In [22]: num_bands = 10
In [23]: [44100*2**(b-num_bands) for b in range(num_bands)]
Out[23]: [43.06640625,  86.1328125,  172.265625,  344.53125,  689.0625,  1378.125,  2756.25,  5512.5,  11025.0,  22050.0]

In [24]: num_bands = 12
In [25]: [44100*2**(b-num_bands) for b in range(num_bands)]
Out[25]: [10.7666015625,  21.533203125,  43.06640625,  86.1328125,  172.265625,  344.53125,  689.0625,  1378.125,  2756.25,  5512.5,  11025.0,  22050.0]

I use these as the maximum frequencies for each band. It works until num_bands = 10 maximum. From 11 and more I start getting very low frequencies out of audible range. Any idea to shrink the range better than this? Maximum frequency of the first band should be at least 40 Hz in any case.

A: Yes, spectrum displays very often convert to dB (or other log scale).
The simplest way to reduce the number of bands is to just add adjacent FFT result bins together in groups per octave (or per half or 12th octave, etc.) of roughly equal ratio between the highest and lowest frequency represented by each band or group of FFT result bins.  Make the ratio-sized groups big or small enough so that you end up with the desired number of total bands.


The first day of life is different for every animal. Human newborns don't do much at all, but some animals hit the ground running. The Caldecott Honor–winning team Steve Jenkins and Robin Page apply their considerable talents to revealing how twenty two different species, from the emperor penguin to the Siberian tiger, adapt to that traumatic first few hours of life, with or without parental help. Jenkins's vividly colorful cut-paper illustrations are eye-poppingly three-dimensional and as exquisite as ever. While the text is short and sweet, an illustrated guide provides descriptions of the twenty two animals in the back. Fantastic!
""[A] handsome examination of child-rearing across the animal kingdom.""
""Jenkins and Page's simple text effectively highlights the differing degrees of independence of a variety of species' young.""
""Jenkins and Page find yet another inviting way to connect young human readers and listeners to creatures who share their world . . . Appealing to a wide age range, this is another crowd pleaser.""
""The striking depictions of mother and child set against full-bleed colored backgrounds or clean white space should make for many return readings.""
""The style would work as an easy read as well as a readaloud.""
""Jenkins's masterly paper collages achieve their usual high standards of zoological accuracy and beauty. The text is shrewdly written in the first-person voice of each baby animal, mingling personality with scientific fact.""


text:
<?php
/**
 * @defgroup FileRepo File Repository
 *
 * @brief This module handles how MediaWiki interacts with filesystems.
 *
 * @details
 */

/**
 * Base code for file repositories.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 * @ingroup FileRepo
 */

/**
 * Base class for file repositories
 *
 * @ingroup FileRepo
 */
class FileRepo {
	const DELETE_SOURCE = 1;
	const OVERWRITE = 2;
	const OVERWRITE_SAME = 4;
	const SKIP_LOCKING = 8;

	const NAME_AND_TIME_ONLY = 1;

	/** @var bool Whether to fetch commons image description pages and display
	 *    them on the local wiki */
	public $fetchDescription;

	/** @var int */
	public $descriptionCacheExpiry;

	/** @var bool */
	protected $hasSha1Storage = false;

	/** @var FileBackend */
	protected $backend;

	/** @var array Map of zones to config */
	protected $zones = array();

	/** @var string URL of thumb.php */
	protected $thumbScriptUrl;

	/** @var bool Whether to skip media file transformation on parse and rely
	 *    on a 404 handler instead. */
	protected $transformVia404;

	/** @var string URL of image description pages, e.g.
	 *    https://en.wikipedia.org/wiki/File:
	 */
	protected $descBaseUrl;

	/** @var string URL of the MediaWiki installation, equivalent to
	 *    $wgScriptPath, e.g. https://en.wikipedia.org/w
	 */
	protected $scriptDirUrl;

	/** @var string Script extension of the MediaWiki installation, equivalent
	 *    to $wgScriptExtension, e.g. .php5 defaults to .php */
	protected $scriptExtension;

	/** @var string Equivalent to $wgArticlePath, e.g. https://en.wikipedia.org/wiki/$1 */
	protected $articleUrl;

	/** @var bool Equivalent to $wgCapitalLinks (or $wgCapitalLinkOverrides[NS_FILE],
	 *    determines whether filenames implicitly start with a capital letter.
	 *    The current implementation may give incorrect description page links
	 *    when the local $wgCapitalLinks and initialCapital are mismatched.
	 */
	protected $initialCapital;

	/** @var string May be 'paranoid' to remove all parameters from error
	 *    messages, 'none' to leave the paths in unchanged, or 'simple' to
	 *    replace paths with placeholders. Default for LocalRepo is
	 *    'simple'.
	 */
	protected $pathDisclosureProtection = 'simple';

	/** @var bool Public zone URL. */
	protected $url;

	/** @var string The base thumbnail URL. Defaults to "<url>/thumb". */
	protected $thumbUrl;

	/** @var int The number of directory levels for hash-based division of files */
	protected $hashLevels;

	/** @var int The number of directory levels for hash-based division of deleted files */
	protected $deletedHashLevels;

	/** @var int File names over this size will use the short form of thumbnail
	 *    names. Short thumbnail names only have the width, parameters, and the
	 *    extension.
	 */
	protected $abbrvThreshold;

	/** @var string The URL of the repo's favicon, if any */
	protected $favicon;

	/** @var bool Whether all zones should be private (e.g. private wiki repo) */
	protected $isPrivate;

	/**
	 * Factory functions for creating new files
	 * Override these in the base class
	 */
	protected $fileFactory = array( 'UnregisteredLocalFile', 'newFromTitle' );
	protected $oldFileFactory = false;
	protected $fileFactoryKey = false;
	protected $oldFileFactoryKey = false;

	/**
	 * @param array|null $info
	 * @throws MWException
	 */
	public function __construct( array $info = null ) {
		// Verify required settings presence
		if (
			$info === null
			|| !array_key_exists( 'name', $info )
			|| !array_key_exists( 'backend', $info )
		) {
			throw new MWException( __CLASS__ .
				" requires an array of options having both 'name' and 'backend' keys.\n" );
		}

		// Required settings
		$this->name = $info['name'];
		if ( $info['backend'] instanceof FileBackend ) {
			$this->backend = $info['backend']; // useful for testing
		} else {
			$this->backend = FileBackendGroup::singleton()->get( $info['backend'] );
		}

		// Optional settings that can have no value
		$optionalSettings = array(
			'descBaseUrl', 'scriptDirUrl', 'articleUrl', 'fetchDescription',
			'thumbScriptUrl', 'pathDisclosureProtection', 'descriptionCacheExpiry',
			'scriptExtension', 'favicon'
		);
		foreach ( $optionalSettings as $var ) {
			if ( isset( $info[$var] ) ) {
				$this->$var = $info[$var];
			}
		}

		// Optional settings that have a default
		$this->initialCapital = isset( $info['initialCapital'] )
			? $info['initialCapital']
			: MWNamespace::isCapitalized( NS_FILE );
		$this->url = isset( $info['url'] )
			? $info['url']
			: false; // a subclass may set the URL (e.g. ForeignAPIRepo)
		if ( isset( $info['thumbUrl'] ) ) {
			$this->thumbUrl = $info['thumbUrl'];
		} else {
			$this->thumbUrl = $this->url ? "{$this->url}/thumb" : false;
		}
		$this->hashLevels = isset( $info['hashLevels'] )
			? $info['hashLevels']
			: 2;
		$this->deletedHashLevels = isset( $info['deletedHashLevels'] )
			? $info['deletedHashLevels']
			: $this->hashLevels;
		$this->transformVia404 = !empty( $info['transformVia404'] );
		$this->abbrvThreshold = isset( $info['abbrvThreshold'] )
			? $info['abbrvThreshold']
			: 255;
		$this->isPrivate = !empty( $info['isPrivate'] );
		// Give defaults for the basic zones...
		$this->zones = isset( $info['zones'] ) ? $info['zones'] : array();
		foreach ( array( 'public', 'thumb', 'transcoded', 'temp', 'deleted' ) as $zone ) {
			if ( !isset( $this->zones[$zone]['container'] ) ) {
				$this->zones[$zone]['container'] = "{$this->name}-{$zone}";
			}
			if ( !isset( $this->zones[$zone]['directory'] ) ) {
				$this->zones[$zone]['directory'] = '';
			}
			if ( !isset( $this->zones[$zone]['urlsByExt'] ) ) {
				$this->zones[$zone]['urlsByExt'] = array();
			}
		}
	}

	/**
	 * Get the file backend instance. Use this function wisely.
	 *
	 * @return FileBackend
	 */
	public function getBackend() {
		return $this->backend;
	}

	/**
	 * Get an explanatory message if this repo is read-only.
	 * This checks if an administrator disabled writes to the backend.
	 *
	 * @return string|bool Returns false if the repo is not read-only
	 */
	public function getReadOnlyReason() {
		return $this->backend->getReadOnlyReason();
	}

	/**
	 * Check if a single zone or list of zones is defined for usage
	 *
	 * @param array $doZones Only do a particular zones
	 * @throws MWException
	 * @return Status
	 */
	protected function initZones( $doZones = array() ) {
		$status = $this->newGood();
		foreach ( (array)$doZones as $zone ) {
			$root = $this->getZonePath( $zone );
			if ( $root === null ) {
				throw new MWException( "No '$zone' zone defined in the {$this->name} repo." );
			}
		}

		return $status;
	}

	/**
	 * Determine if a string is an mwrepo:// URL
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function isVirtualUrl( $url ) {
		return substr( $url, 0, 9 ) == 'mwrepo://';
	}

	/**
	 * Get a URL referring to this repository, with the private mwrepo protocol.
	 * The suffix, if supplied, is considered to be unencoded, and will be
	 * URL-encoded before being returned.
	 *
	 * @param string|bool $suffix
	 * @return string
	 */
	public function getVirtualUrl( $suffix = false ) {
		$path = 'mwrepo://' . $this->name;
		if ( $suffix !== false ) {
			$path .= '/' . rawurlencode( $suffix );
		}

		return $path;
	}

	/**
	 * Get the URL corresponding to one of the four basic zones
	 *
	 * @param string $zone One of: public, deleted, temp, thumb
	 * @param string|null $ext Optional file extension
	 * @return string|bool
	 */
	public function getZoneUrl( $zone, $ext = null ) {
		if ( in_array( $zone, array( 'public', 'thumb', 'transcoded' ) ) ) {
			// standard public zones
			if ( $ext !== null && isset( $this->zones[$zone]['urlsByExt'][$ext] ) ) {
				// custom URL for extension/zone
				return $this->zones[$zone]['urlsByExt'][$ext];
			} elseif ( isset( $this->zones[$zone]['url'] ) ) {
				// custom URL for zone
				return $this->zones[$zone]['url'];
			}
		}
		switch ( $zone ) {
			case 'public':
				return $this->url;
			case 'temp':
			case 'deleted':
				return false; // no public URL
			case 'thumb':
				return $this->thumbUrl;
			case 'transcoded':
				return "{$this->url}/transcoded";
			default:
				return false;
		}
	}

	/**
	 * @return bool Whether non-ASCII path characters are allowed
	 */
	public function backendSupportsUnicodePaths() {
		return ( $this->getBackend()->getFeatures() & FileBackend::ATTR_UNICODE_PATHS );
	}

	/**
	 * Get the backend storage path corresponding to a virtual URL.
	 * Use this function wisely.
	 *
	 * @param string $url
	 * @throws MWException
	 * @return string
	 */
	public function resolveVirtualUrl( $url ) {
		if ( substr( $url, 0, 9 ) != 'mwrepo://' ) {
			throw new MWException( __METHOD__ . ': unknown protocol' );
		}
		$bits = explode( '/', substr( $url, 9 ), 3 );
		if ( count( $bits ) != 3 ) {
			throw new MWException( __METHOD__ . ": invalid mwrepo URL: $url" );
		}
		list( $repo, $zone, $rel ) = $bits;
		if ( $repo !== $this->name ) {
			throw new MWException( __METHOD__ . ": fetching from a foreign repo is not supported" );
		}
		$base = $this->getZonePath( $zone );
		if ( !$base ) {
			throw new MWException( __METHOD__ . ": invalid zone: $zone" );
		}

		return $base . '/' . rawurldecode( $rel );
	}

	/**
	 * The the storage container and base path of a zone
	 *
	 * @param string $zone
	 * @return array (container, base path) or (null, null)
	 */
	protected function getZoneLocation( $zone ) {
		if ( !isset( $this->zones[$zone] ) ) {
			return array( null, null ); // bogus
		}

		return array( $this->zones[$zone]['container'], $this->zones[$zone]['directory'] );
	}

	/**
	 * Get the storage path corresponding to one of the zones
	 *
	 * @param string $zone
	 * @return string|null Returns null if the zone is not defined
	 */
	public function getZonePath( $zone ) {
		list( $container, $base ) = $this->getZoneLocation( $zone );
		if ( $container === null || $base === null ) {
			return null;
		}
		$backendName = $this->backend->getName();
		if ( $base != '' ) { // may not be set
			$base = "/{$base}";
		}

		return "mwstore://$backendName/{$container}{$base}";
	}

	/**
	 * Create a new File object from the local repository
	 *
	 * @param Title|string $title Title object or string
	 * @param bool|string $time Time at which the image was uploaded. If this
	 *   is specified, the returned object will be an instance of the
	 *   repository's old file class instead of a current file. Repositories
	 *   not supporting version control should return false if this parameter
	 *   is set.
	 * @return File|null A File, or null if passed an invalid Title
	 */
	public function newFile( $title, $time = false ) {
		$title = File::normalizeTitle( $title );
		if ( !$title ) {
			return null;
		}
		if ( $time ) {
			if ( $this->oldFileFactory ) {
				return call_user_func( $this->oldFileFactory, $title, $this, $time );
			} else {
				return false;
			}
		} else {
			return call_user_func( $this->fileFactory, $title, $this );
		}
	}

	/**
	 * Find an instance of the named file created at the specified time
	 * Returns false if the file does not exist. Repositories not supporting
	 * version control should return false if the time is specified.
	 *
	 * @param Title|string $title Title object or string
	 * @param array $options Associative array of options:
	 *   time:           requested time for a specific file version, or false for the
	 *                   current version. An image object will be returned which was
	 *                   created at the specified time (which may be archived or current).
	 *   ignoreRedirect: If true, do not follow file redirects
	 *   private:        If true, return restricted (deleted) files if the current
	 *                   user is allowed to view them. Otherwise, such files will not
	 *                   be found. If a User object, use that user instead of the current.
	 *   latest:         If true, load from the latest available data into File objects
	 * @return File|bool False on failure
	 */
	public function findFile( $title, $options = array() ) {
		$title = File::normalizeTitle( $title );
		if ( !$title ) {
			return false;
		}
		if ( isset( $options['bypassCache'] ) ) {
			$options['latest'] = $options['bypassCache']; // b/c
		}
		$time = isset( $options['time'] ) ? $options['time'] : false;
		$flags = !empty( $options['latest'] ) ? File::READ_LATEST : 0;
		# First try the current version of the file to see if it precedes the timestamp
		$img = $this->newFile( $title );
		if ( !$img ) {
			return false;
		}
		$img->load( $flags );
		if ( $img->exists() && ( !$time || $img->getTimestamp() == $time ) ) {
			return $img;
		}
		# Now try an old version of the file
		if ( $time !== false ) {
			$img = $this->newFile( $title, $time );
			if ( $img ) {
				$img->load( $flags );
				if ( $img->exists() ) {
					if ( !$img->isDeleted( File::DELETED_FILE ) ) {
						return $img; // always OK
					} elseif ( !empty( $options['private'] ) &&
						$img->userCan( File::DELETED_FILE,
							$options['private'] instanceof User ? $options['private'] : null
						)
					) {
						return $img;
					}
				}
			}
		}

		# Now try redirects
		if ( !empty( $options['ignoreRedirect'] ) ) {
			return false;
		}
		$redir = $this->checkRedirect( $title );
		if ( $redir && $title->getNamespace() == NS_FILE ) {
			$img = $this->newFile( $redir );
			if ( !$img ) {
				return false;
			}
			$img->load( $flags );
			if ( $img->exists() ) {
				$img->redirectedFrom( $title->getDBkey() );

				return $img;
			}
		}

		return false;
	}

	/**
	 * Find many files at once.
	 *
	 * @param array $items An array of titles, or an array of findFile() options with
	 *    the "title" option giving the title. Example:
	 *
	 *     $findItem = array( 'title' => $title, 'private' => true );
	 *     $findBatch = array( $findItem );
	 *     $repo->findFiles( $findBatch );
	 *
	 *    No title should appear in $items twice, as the result use titles as keys
	 * @param int $flags Supports:
	 *     - FileRepo::NAME_AND_TIME_ONLY : return a (search title => (title,timestamp)) map.
	 *       The search title uses the input titles; the other is the final post-redirect title.
	 *       All titles are returned as string DB keys and the inner array is associative.
	 * @return array Map of (file name => File objects) for matches
	 */
	public function findFiles( array $items, $flags = 0 ) {
		$result = array();
		foreach ( $items as $item ) {
			if ( is_array( $item ) ) {
				$title = $item['title'];
				$options = $item;
				unset( $options['title'] );
			} else {
				$title = $item;
				$options = array();
			}
			$file = $this->findFile( $title, $options );
			if ( $file ) {
				$searchName = File::normalizeTitle( $title )->getDBkey(); // must be valid
				if ( $flags & self::NAME_AND_TIME_ONLY ) {
					$result[$searchName] = array(
						'title' => $file->getTitle()->getDBkey(),
						'timestamp' => $file->getTimestamp()
					);
				} else {
					$result[$searchName] = $file;
				}
			}
		}

		return $result;
	}

	/**
	 * Find an instance of the file with this key, created at the specified time
	 * Returns false if the file does not exist. Repositories not supporting
	 * version control should return false if the time is specified.
	 *
	 * @param string $sha1 Base 36 SHA-1 hash
	 * @param array $options Option array, same as findFile().
	 * @return File|bool False on failure
	 */
	public function findFileFromKey( $sha1, $options = array() ) {
		$time = isset( $options['time'] ) ? $options['time'] : false;
		# First try to find a matching current version of a file...
		if ( $this->fileFactoryKey ) {
			$img = call_user_func( $this->fileFactoryKey, $sha1, $this, $time );
		} else {
			return false; // find-by-sha1 not supported
		}
		if ( $img && $img->exists() ) {
			return $img;
		}
		# Now try to find a matching old version of a file...
		if ( $time !== false && $this->oldFileFactoryKey ) { // find-by-sha1 supported?
			$img = call_user_func( $this->oldFileFactoryKey, $sha1, $this, $time );
			if ( $img && $img->exists() ) {
				if ( !$img->isDeleted( File::DELETED_FILE ) ) {
					return $img; // always OK
				} elseif ( !empty( $options['private'] ) &&
					$img->userCan( File::DELETED_FILE,
						$options['private'] instanceof User ? $options['private'] : null
					)
				) {
					return $img;
				}
			}
		}

		return false;
	}

	/**
	 * Get an array or iterator of file objects for files that have a given
	 * SHA-1 content hash.
	 *
	 * STUB
	 * @param string $hash SHA-1 hash
	 * @return File[]
	 */
	public function findBySha1( $hash ) {
		return array();
	}

	/**
	 * Get an array of arrays or iterators of file objects for files that
	 * have the given SHA-1 content hashes.
	 *
	 * @param array $hashes An array of hashes
	 * @return array An Array of arrays or iterators of file objects and the hash as key
	 */
	public function findBySha1s( array $hashes ) {
		$result = array();
		foreach ( $hashes as $hash ) {
			$files = $this->findBySha1( $hash );
			if ( count( $files ) ) {
				$result[$hash] = $files;
			}
		}

		return $result;
	}

	/**
	 * Return an array of files where the name starts with $prefix.
	 *
	 * STUB
	 * @param string $prefix The prefix to search for
	 * @param int $limit The maximum amount of files to return
	 * @return array
	 */
	public function findFilesByPrefix( $prefix, $limit ) {
		return array();
	}

	/**
	 * Get the public root URL of the repository
	 *
	 * @deprecated since 1.20
	 * @return string
	 */
	public function getRootUrl() {
		return $this->getZoneUrl( 'public' );
	}

	/**
	 * Get the URL of thumb.php
	 *
	 * @return string
	 */
	public function getThumbScriptUrl() {
		return $this->thumbScriptUrl;
	}

	/**
	 * Returns true if the repository can transform files via a 404 handler
	 *
	 * @return bool
	 */
	public function canTransformVia404() {
		return $this->transformVia404;
	}

	/**
	 * Get the name of a file from its title object
	 *
	 * @param Title $title
	 * @return string
	 */
	public function getNameFromTitle( Title $title ) {
		global $wgContLang;
		if ( $this->initialCapital != MWNamespace::isCapitalized( NS_FILE ) ) {
			$name = $title->getUserCaseDBKey();
			if ( $this->initialCapital ) {
				$name = $wgContLang->ucfirst( $name );
			}
		} else {
			$name = $title->getDBkey();
		}

		return $name;
	}

	/**
	 * Get the public zone root storage directory of the repository
	 *
	 * @return string
	 */
	public function getRootDirectory() {
		return $this->getZonePath( 'public' );
	}

	/**
	 * Get a relative path including trailing slash, e.g. f/fa/
	 * If the repo is not hashed, returns an empty string
	 *
	 * @param string $name Name of file
	 * @return string
	 */
	public function getHashPath( $name ) {
		return self::getHashPathForLevel( $name, $this->hashLevels );
	}

	/**
	 * Get a relative path including trailing slash, e.g. f/fa/
	 * If the repo is not hashed, returns an empty string
	 *
	 * @param string $suffix Basename of file from FileRepo::storeTemp()
	 * @return string
	 */
	public function getTempHashPath( $suffix ) {
		$parts = explode( '!', $suffix, 2 ); // format is <timestamp>!<name> or just <name>
		$name = isset( $parts[1] ) ? $parts[1] : $suffix; // hash path is not based on timestamp
		return self::getHashPathForLevel( $name, $this->hashLevels );
	}

	/**
	 * @param string $name
	 * @param int $levels
	 * @return string
	 */
	protected static function getHashPathForLevel( $name, $levels ) {
		if ( $levels == 0 ) {
			return '';
		} else {
			$hash = md5( $name );
			$path = '';
			for ( $i = 1; $i <= $levels; $i++ ) {
				$path .= substr( $hash, 0, $i ) . '/';
			}

			return $path;
		}
	}

	/**
	 * Get the number of hash directory levels
	 *
	 * @return int
	 */
	public function getHashLevels() {
		return $this->hashLevels;
	}

	/**
	 * Get the name of this repository, as specified by $info['name]' to the constructor
	 *
	 * @return string
	 */
	public function getName() {
		return $this->name;
	}

	/**
	 * Make an url to this repo
	 *
	 * @param string $query Query string to append
	 * @param string $entry Entry point; defaults to index
	 * @return string|bool False on failure
	 */
	public function makeUrl( $query = '', $entry = 'index' ) {
		if ( isset( $this->scriptDirUrl ) ) {
			$ext = isset( $this->scriptExtension ) ? $this->scriptExtension : '.php';

			return wfAppendQuery( "{$this->scriptDirUrl}/{$entry}{$ext}", $query );
		}

		return false;
	}

	/**
	 * Get the URL of an image description page. May return false if it is
	 * unknown or not applicable. In general this should only be called by the
	 * File class, since it may return invalid results for certain kinds of
	 * repositories. Use File::getDescriptionUrl() in user code.
	 *
	 * In particular, it uses the article paths as specified to the repository
	 * constructor, whereas local repositories use the local Title functions.
	 *
	 * @param string $name
	 * @return string
	 */
	public function getDescriptionUrl( $name ) {
		$encName = wfUrlencode( $name );
		if ( !is_null( $this->descBaseUrl ) ) {
			# "http://example.com/wiki/File:"
			return $this->descBaseUrl . $encName;
		}
		if ( !is_null( $this->articleUrl ) ) {
			# "http://example.com/wiki/$1"
			#
			# We use "Image:" as the canonical namespace for
			# compatibility across all MediaWiki versions.
			return str_replace( '$1',
				"Image:$encName", $this->articleUrl );
		}
		if ( !is_null( $this->scriptDirUrl ) ) {
			# "http://example.com/w"
			#
			# We use "Image:" as the canonical namespace for
			# compatibility across all MediaWiki versions,
			# and just sort of hope index.php is right. ;)
			return $this->makeUrl( "title=Image:$encName" );
		}

		return false;
	}

	/**
	 * Get the URL of the content-only fragment of the description page. For
	 * MediaWiki this means action=render. This should only be called by the
	 * repository's file class, since it may return invalid results. User code
	 * should use File::getDescriptionText().
	 *
	 * @param string $name Name of image to fetch
	 * @param string $lang Language to fetch it in, if any.
	 * @return string
	 */
	public function getDescriptionRenderUrl( $name, $lang = null ) {
		$query = 'action=render';
		if ( !is_null( $lang ) ) {
			$query .= '&uselang=' . $lang;
		}
		if ( isset( $this->scriptDirUrl ) ) {
			return $this->makeUrl(
				'title=' .
				wfUrlencode( 'Image:' . $name ) .
				"&$query" );
		} else {
			$descUrl = $this->getDescriptionUrl( $name );
			if ( $descUrl ) {
				return wfAppendQuery( $descUrl, $query );
			} else {
				return false;
			}
		}
	}

	/**
	 * Get the URL of the stylesheet to apply to description pages
	 *
	 * @return string|bool False on failure
	 */
	public function getDescriptionStylesheetUrl() {
		if ( isset( $this->scriptDirUrl ) ) {
			return $this->makeUrl( 'title=MediaWiki:Filepage.css&' .
				wfArrayToCgi( Skin::getDynamicStylesheetQuery() ) );
		}

		return false;
	}

	/**
	 * Store a file to a given destination.
	 *
	 * @param string $srcPath Source file system path, storage path, or virtual URL
	 * @param string $dstZone Destination zone
	 * @param string $dstRel Destination relative path
	 * @param int $flags Bitwise combination of the following flags:
	 *   self::DELETE_SOURCE     Delete the source file after upload
	 *   self::OVERWRITE         Overwrite an existing destination file instead of failing
	 *   self::OVERWRITE_SAME    Overwrite the file if the destination exists and has the
	 *                           same contents as the source
	 *   self::SKIP_LOCKING      Skip any file locking when doing the store
	 * @return FileRepoStatus
	 */
	public function store( $srcPath, $dstZone, $dstRel, $flags = 0 ) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->storeBatch( array( array( $srcPath, $dstZone, $dstRel ) ), $flags );
		if ( $status->successCount == 0 ) {
			$status->ok = false;
		}

		return $status;
	}

	/**
	 * Store a batch of files
	 *
	 * @param array $triplets (src, dest zone, dest rel) triplets as per store()
	 * @param int $flags Bitwise combination of the following flags:
	 *   self::DELETE_SOURCE     Delete the source file after upload
	 *   self::OVERWRITE         Overwrite an existing destination file instead of failing
	 *   self::OVERWRITE_SAME    Overwrite the file if the destination exists and has the
	 *                           same contents as the source
	 *   self::SKIP_LOCKING      Skip any file locking when doing the store
	 * @throws MWException
	 * @return FileRepoStatus
	 */
	public function storeBatch( array $triplets, $flags = 0 ) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->newGood();
		$backend = $this->backend; // convenience

		$operations = array();
		$sourceFSFilesToDelete = array(); // cleanup for disk source files
		// Validate each triplet and get the store operation...
		foreach ( $triplets as $triplet ) {
			list( $srcPath, $dstZone, $dstRel ) = $triplet;
			wfDebug( __METHOD__
				. "( \$src='$srcPath', \$dstZone='$dstZone', \$dstRel='$dstRel' )\n"
			);

			// Resolve destination path
			$root = $this->getZonePath( $dstZone );
			if ( !$root ) {
				throw new MWException( "Invalid zone: $dstZone" );
			}
			if ( !$this->validateFilename( $dstRel ) ) {
				throw new MWException( 'Validation error in $dstRel' );
			}
			$dstPath = "$root/$dstRel";
			$dstDir = dirname( $dstPath );
			// Create destination directories for this triplet
			if ( !$this->initDirectory( $dstDir )->isOK() ) {
				return $this->newFatal( 'directorycreateerror', $dstDir );
			}

			// Resolve source to a storage path if virtual
			$srcPath = $this->resolveToStoragePath( $srcPath );

			// Get the appropriate file operation
			if ( FileBackend::isStoragePath( $srcPath ) ) {
				$opName = ( $flags & self::DELETE_SOURCE ) ? 'move' : 'copy';
			} else {
				$opName = 'store';
				if ( $flags & self::DELETE_SOURCE ) {
					$sourceFSFilesToDelete[] = $srcPath;
				}
			}
			$operations[] = array(
				'op' => $opName,
				'src' => $srcPath,
				'dst' => $dstPath,
				'overwrite' => $flags & self::OVERWRITE,
				'overwriteSame' => $flags & self::OVERWRITE_SAME,
			);
		}

		// Execute the store operation for each triplet
		$opts = array( 'force' => true );
		if ( $flags & self::SKIP_LOCKING ) {
			$opts['nonLocking'] = true;
		}
		$status->merge( $backend->doOperations( $operations, $opts ) );
		// Cleanup for disk source files...
		foreach ( $sourceFSFilesToDelete as $file ) {
			MediaWiki\suppressWarnings();
			unlink( $file ); // FS cleanup
			MediaWiki\restoreWarnings();
		}

		return $status;
	}

	/**
	 * Deletes a batch of files.
	 * Each file can be a (zone, rel) pair, virtual url, storage path.
	 * It will try to delete each file, but ignores any errors that may occur.
	 *
	 * @param array $files List of files to delete
	 * @param int $flags Bitwise combination of the following flags:
	 *   self::SKIP_LOCKING      Skip any file locking when doing the deletions
	 * @return FileRepoStatus
	 */
	public function cleanupBatch( array $files, $flags = 0 ) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->newGood();

		$operations = array();
		foreach ( $files as $path ) {
			if ( is_array( $path ) ) {
				// This is a pair, extract it
				list( $zone, $rel ) = $path;
				$path = $this->getZonePath( $zone ) . "/$rel";
			} else {
				// Resolve source to a storage path if virtual
				$path = $this->resolveToStoragePath( $path );
			}
			$operations[] = array( 'op' => 'delete', 'src' => $path );
		}
		// Actually delete files from storage...
		$opts = array( 'force' => true );
		if ( $flags & self::SKIP_LOCKING ) {
			$opts['nonLocking'] = true;
		}
		$status->merge( $this->backend->doOperations( $operations, $opts ) );

		return $status;
	}

	/**
	 * Import a file from the local file system into the repo.
	 * This does no locking nor journaling and overrides existing files.
	 * This function can be used to write to otherwise read-only foreign repos.
	 * This is intended for copying generated thumbnails into the repo.
	 *
	 * @param string $src Source file system path, storage path, or virtual URL
	 * @param string $dst Virtual URL or storage path
	 * @param array|string|null $options An array consisting of a key named headers
	 *   listing extra headers. If a string, taken as content-disposition header.
	 *   (Support for array of options new in 1.23)
	 * @return FileRepoStatus
	 */
	final public function quickImport( $src, $dst, $options = null ) {
		return $this->quickImportBatch( array( array( $src, $dst, $options ) ) );
	}

	/**
	 * Purge a file from the repo. This does no locking nor journaling.
	 * This function can be used to write to otherwise read-only foreign repos.
	 * This is intended for purging thumbnails.
	 *
	 * @param string $path Virtual URL or storage path
	 * @return FileRepoStatus
	 */
	final public function quickPurge( $path ) {
		return $this->quickPurgeBatch( array( $path ) );
	}

	/**
	 * Deletes a directory if empty.
	 * This function can be used to write to otherwise read-only foreign repos.
	 *
	 * @param string $dir Virtual URL (or storage path) of directory to clean
	 * @return Status
	 */
	public function quickCleanDir( $dir ) {
		$status = $this->newGood();
		$status->merge( $this->backend->clean(
			array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );

		return $status;
	}

	/**
	 * Import a batch of files from the local file system into the repo.
	 * This does no locking nor journaling and overrides existing files.
	 * This function can be used to write to otherwise read-only foreign repos.
	 * This is intended for copying generated thumbnails into the repo.
	 *
	 * All path parameters may be a file system path, storage path, or virtual URL.
	 * When "headers" are given they are used as HTTP headers if supported.
	 *
	 * @param array $triples List of (source path, destination path, disposition)
	 * @return FileRepoStatus
	 */
	public function quickImportBatch( array $triples ) {
		$status = $this->newGood();
		$operations = array();
		foreach ( $triples as $triple ) {
			list( $src, $dst ) = $triple;
			$src = $this->resolveToStoragePath( $src );
			$dst = $this->resolveToStoragePath( $dst );

			if ( !isset( $triple[2] ) ) {
				$headers = array();
			} elseif ( is_string( $triple[2] ) ) {
				// back-compat
				$headers = array( 'Content-Disposition' => $triple[2] );
			} elseif ( is_array( $triple[2] ) && isset( $triple[2]['headers'] ) ) {
				$headers = $triple[2]['headers'];
			}
			// @fixme: $headers might not be defined
			$operations[] = array(
				'op' => FileBackend::isStoragePath( $src ) ? 'copy' : 'store',
				'src' => $src,
				'dst' => $dst,
				'headers' => $headers
			);
			$status->merge( $this->initDirectory( dirname( $dst ) ) );
		}
		$status->merge( $this->backend->doQuickOperations( $operations ) );

		return $status;
	}

	/**
	 * Purge a batch of files from the repo.
	 * This function can be used to write to otherwise read-only foreign repos.
	 * This does no locking nor journaling and is intended for purging thumbnails.
	 *
	 * @param array $paths List of virtual URLs or storage paths
	 * @return FileRepoStatus
	 */
	public function quickPurgeBatch( array $paths ) {
		$status = $this->newGood();
		$operations = array();
		foreach ( $paths as $path ) {
			$operations[] = array(
				'op' => 'delete',
				'src' => $this->resolveToStoragePath( $path ),
				'ignoreMissingSource' => true
			);
		}
		$status->merge( $this->backend->doQuickOperations( $operations ) );

		return $status;
	}

	/**
	 * Pick a random name in the temp zone and store a file to it.
	 * Returns a FileRepoStatus object with the file Virtual URL in the value,
	 * file can later be disposed using FileRepo::freeTemp().
	 *
	 * @param string $originalName The base name of the file as specified
	 *   by the user. The file extension will be maintained.
	 * @param string $srcPath The current location of the file.
	 * @return FileRepoStatus Object with the URL in the value.
	 */
	public function storeTemp( $originalName, $srcPath ) {
		$this->assertWritableRepo(); // fail out if read-only

		$date = MWTimestamp::getInstance()->format( 'YmdHis' );
		$hashPath = $this->getHashPath( $originalName );
		$dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName );
		$virtualUrl = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel;

		$result = $this->quickImport( $srcPath, $virtualUrl );
		$result->value = $virtualUrl;

		return $result;
	}

	/**
	 * Remove a temporary file or mark it for garbage collection
	 *
	 * @param string $virtualUrl The virtual URL returned by FileRepo::storeTemp()
	 * @return bool True on success, false on failure
	 */
	public function freeTemp( $virtualUrl ) {
		$this->assertWritableRepo(); // fail out if read-only

		$temp = $this->getVirtualUrl( 'temp' );
		if ( substr( $virtualUrl, 0, strlen( $temp ) ) != $temp ) {
			wfDebug( __METHOD__ . ": Invalid temp virtual URL\n" );

			return false;
		}

		return $this->quickPurge( $virtualUrl )->isOK();
	}

	/**
	 * Concatenate a list of temporary files into a target file location.
	 *
	 * @param array $srcPaths Ordered list of source virtual URLs/storage paths
	 * @param string $dstPath Target file system path
	 * @param int $flags Bitwise combination of the following flags:
	 *   self::DELETE_SOURCE     Delete the source files
	 * @return FileRepoStatus
	 */
	public function concatenate( array $srcPaths, $dstPath, $flags = 0 ) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->newGood();

		$sources = array();
		foreach ( $srcPaths as $srcPath ) {
			// Resolve source to a storage path if virtual
			$source = $this->resolveToStoragePath( $srcPath );
			$sources[] = $source; // chunk to merge
		}

		// Concatenate the chunks into one FS file
		$params = array( 'srcs' => $sources, 'dst' => $dstPath );
		$status->merge( $this->backend->concatenate( $params ) );
		if ( !$status->isOK() ) {
			return $status;
		}

		// Delete the sources if required
		if ( $flags & self::DELETE_SOURCE ) {
			$status->merge( $this->quickPurgeBatch( $srcPaths ) );
		}

		// Make sure status is OK, despite any quickPurgeBatch() fatals
		$status->setResult( true );

		return $status;
	}

	/**
	 * Copy or move a file either from a storage path, virtual URL,
	 * or file system path, into this repository at the specified destination location.
	 *
	 * Returns a FileRepoStatus object. On success, the value contains "new" or
	 * "archived", to indicate whether the file was new with that name.
	 *
	 * Options to $options include:
	 *   - headers : name/value map of HTTP headers to use in response to GET/HEAD requests
	 *
	 * @param string $srcPath The source file system path, storage path, or URL
	 * @param string $dstRel The destination relative path
	 * @param string $archiveRel The relative path where the existing file is to
	 *   be archived, if there is one. Relative to the public zone root.
	 * @param int $flags Bitfield, may be FileRepo::DELETE_SOURCE to indicate
	 *   that the source file should be deleted if possible
	 * @param array $options Optional additional parameters
	 * @return FileRepoStatus
	 */
	public function publish(
		$srcPath, $dstRel, $archiveRel, $flags = 0, array $options = array()
	) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->publishBatch(
			array( array( $srcPath, $dstRel, $archiveRel, $options ) ), $flags );
		if ( $status->successCount == 0 ) {
			$status->ok = false;
		}
		if ( isset( $status->value[0] ) ) {
			$status->value = $status->value[0];
		} else {
			$status->value = false;
		}

		return $status;
	}

	/**
	 * Publish a batch of files
	 *
	 * @param array $ntuples (source, dest, archive) triplets or
	 *   (source, dest, archive, options) 4-tuples as per publish().
	 * @param int $flags Bitfield, may be FileRepo::DELETE_SOURCE to indicate
	 *   that the source files should be deleted if possible
	 * @throws MWException
	 * @return FileRepoStatus
	 */
	public function publishBatch( array $ntuples, $flags = 0 ) {
		$this->assertWritableRepo(); // fail out if read-only

		$backend = $this->backend; // convenience
		// Try creating directories
		$status = $this->initZones( 'public' );
		if ( !$status->isOK() ) {
			return $status;
		}

		$status = $this->newGood( array() );

		$operations = array();
		$sourceFSFilesToDelete = array(); // cleanup for disk source files
		// Validate each triplet and get the store operation...
		foreach ( $ntuples as $ntuple ) {
			list( $srcPath, $dstRel, $archiveRel ) = $ntuple;
			$options = isset( $ntuple[3] ) ? $ntuple[3] : array();
			// Resolve source to a storage path if virtual
			$srcPath = $this->resolveToStoragePath( $srcPath );
			if ( !$this->validateFilename( $dstRel ) ) {
				throw new MWException( 'Validation error in $dstRel' );
			}
			if ( !$this->validateFilename( $archiveRel ) ) {
				throw new MWException( 'Validation error in $archiveRel' );
			}

			$publicRoot = $this->getZonePath( 'public' );
			$dstPath = "$publicRoot/$dstRel";
			$archivePath = "$publicRoot/$archiveRel";

			$dstDir = dirname( $dstPath );
			$archiveDir = dirname( $archivePath );
			// Abort immediately on directory creation errors since they're likely to be repetitive
			if ( !$this->initDirectory( $dstDir )->isOK() ) {
				return $this->newFatal( 'directorycreateerror', $dstDir );
			}
			if ( !$this->initDirectory( $archiveDir )->isOK() ) {
				return $this->newFatal( 'directorycreateerror', $archiveDir );
			}

			// Set any desired headers to be use in GET/HEAD responses
			$headers = isset( $options['headers'] ) ? $options['headers'] : array();

			// Archive destination file if it exists.
			// This will check if the archive file also exists and fail if does.
			// This is a sanity check to avoid data loss. On Windows and Linux,
			// copy() will overwrite, so the existence check is vulnerable to
			// race conditions unless a functioning LockManager is used.
			// LocalFile also uses SELECT FOR UPDATE for synchronization.
			$operations[] = array(
				'op' => 'copy',
				'src' => $dstPath,
				'dst' => $archivePath,
				'ignoreMissingSource' => true
			);

			// Copy (or move) the source file to the destination
			if ( FileBackend::isStoragePath( $srcPath ) ) {
				if ( $flags & self::DELETE_SOURCE ) {
					$operations[] = array(
						'op' => 'move',
						'src' => $srcPath,
						'dst' => $dstPath,
						'overwrite' => true, // replace current
						'headers' => $headers
					);
				} else {
					$operations[] = array(
						'op' => 'copy',
						'src' => $srcPath,
						'dst' => $dstPath,
						'overwrite' => true, // replace current
						'headers' => $headers
					);
				}
			} else { // FS source path
				$operations[] = array(
					'op' => 'store',
					'src' => $srcPath,
					'dst' => $dstPath,
					'overwrite' => true, // replace current
					'headers' => $headers
				);
				if ( $flags & self::DELETE_SOURCE ) {
					$sourceFSFilesToDelete[] = $srcPath;
				}
			}
		}

		// Execute the operations for each triplet
		$status->merge( $backend->doOperations( $operations ) );
		// Find out which files were archived...
		foreach ( $ntuples as $i => $ntuple ) {
			list( , , $archiveRel ) = $ntuple;
			$archivePath = $this->getZonePath( 'public' ) . "/$archiveRel";
			if ( $this->fileExists( $archivePath ) ) {
				$status->value[$i] = 'archived';
			} else {
				$status->value[$i] = 'new';
			}
		}
		// Cleanup for disk source files...
		foreach ( $sourceFSFilesToDelete as $file ) {
			MediaWiki\suppressWarnings();
			unlink( $file ); // FS cleanup
			MediaWiki\restoreWarnings();
		}

		return $status;
	}

	/**
	 * Creates a directory with the appropriate zone permissions.
	 * Callers are responsible for doing read-only and "writable repo" checks.
	 *
	 * @param string $dir Virtual URL (or storage path) of directory to clean
	 * @return Status
	 */
	protected function initDirectory( $dir ) {
		$path = $this->resolveToStoragePath( $dir );
		list( , $container, ) = FileBackend::splitStoragePath( $path );

		$params = array( 'dir' => $path );
		if ( $this->isPrivate
			|| $container === $this->zones['deleted']['container']
			|| $container === $this->zones['temp']['container']
		) {
			# Take all available measures to prevent web accessibility of new deleted
			# directories, in case the user has not configured offline storage
			$params = array( 'noAccess' => true, 'noListing' => true ) + $params;
		}

		return $this->backend->prepare( $params );
	}

	/**
	 * Deletes a directory if empty.
	 *
	 * @param string $dir Virtual URL (or storage path) of directory to clean
	 * @return Status
	 */
	public function cleanDir( $dir ) {
		$this->assertWritableRepo(); // fail out if read-only

		$status = $this->newGood();
		$status->merge( $this->backend->clean(
			array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );

		return $status;
	}

	/**
	 * Checks existence of a a file
	 *
	 * @param string $file Virtual URL (or storage path) of file to check
	 * @return bool
	 */
	public function fileExists( $file ) {
		$result = $this->fileExistsBatch( array( $file ) );

		return $result[0];
	}

	/**
	 * Checks existence of an array of files.
	 *
	 * @param array $files Virtual URLs (or storage paths) of files to check
	 * @return array Map of files and existence flags, or false
	 */
	public function fileExistsBatch( array $files ) {
		$paths = array_map( array( $this, 'resolveToStoragePath' ), $files );
		$this->backend->preloadFileStat( array( 'srcs' => $paths ) );

		$result = array();
		foreach ( $files as $key => $file ) {
			$path = $this->resolveToStoragePath( $file );
			$result[$key] = $this->backend->fileExists( array( 'src' => $path ) );
		}

		return $result;
	}

	/**
	 * Move a file to the deletion archive.
	 * If no valid deletion archive exists, this may either delete the file
	 * or throw an exception, depending on the preference of the repository
	 *
	 * @param mixed $srcRel Relative path for the file to be deleted
	 * @param mixed $archiveRel Relative path for the archive location.
	 *   Relative to a private archive directory.
	 * @return FileRepoStatus
	 */
	public function delete( $srcRel, $archiveRel ) {
		$this->assertWritableRepo(); // fail out if read-only

		return $this->deleteBatch( array( array( $srcRel, $archiveRel ) ) );
	}

	/**
	 * Move a group of files to the deletion archive.
	 *
	 * If no valid deletion archive is configured, this may either delete the
	 * file or throw an exception, depending on the preference of the repository.
	 *
	 * The overwrite policy is determined by the repository -- currently LocalRepo
	 * assumes a naming scheme in the deleted zone based on content hash, as
	 * opposed to the public zone which is assumed to be unique.
	 *
	 * @param array $sourceDestPairs Array of source/destination pairs. Each element
	 *   is a two-element array containing the source file path relative to the
	 *   public root in the first element, and the archive file path relative
	 *   to the deleted zone root in the second element.
	 * @throws MWException
	 * @return FileRepoStatus
	 */
	public function deleteBatch( array $sourceDestPairs ) {
		$this->assertWritableRepo(); // fail out if read-only

		// Try creating directories
		$status = $this->initZones( array( 'public', 'deleted' ) );
		if ( !$status->isOK() ) {
			return $status;
		}

		$status = $this->newGood();

		$backend = $this->backend; // convenience
		$operations = array();
		// Validate filenames and create archive directories
		foreach ( $sourceDestPairs as $pair ) {
			list( $srcRel, $archiveRel ) = $pair;
			if ( !$this->validateFilename( $srcRel ) ) {
				throw new MWException( __METHOD__ . ':Validation error in $srcRel' );
			} elseif ( !$this->validateFilename( $archiveRel ) ) {
				throw new MWException( __METHOD__ . ':Validation error in $archiveRel' );
			}

			$publicRoot = $this->getZonePath( 'public' );
			$srcPath = "{$publicRoot}/$srcRel";

			$deletedRoot = $this->getZonePath( 'deleted' );
			$archivePath = "{$deletedRoot}/{$archiveRel}";
			$archiveDir = dirname( $archivePath ); // does not touch FS

			// Create destination directories
			if ( !$this->initDirectory( $archiveDir )->isOK() ) {
				return $this->newFatal( 'directorycreateerror', $archiveDir );
			}

			$operations[] = array(
				'op' => 'move',
				'src' => $srcPath,
				'dst' => $archivePath,
				// We may have 2+ identical files being deleted,
				// all of which will map to the same destination file
				'overwriteSame' => true // also see bug 31792
			);
		}

		// Move the files by execute the operations for each pair.
		// We're now committed to returning an OK result, which will
		// lead to the files being moved in the DB also.
		$opts = array( 'force' => true );
		$status->merge( $backend->doOperations( $operations, $opts ) );

		return $status;
	}

	/**
	 * Delete files in the deleted directory if they are not referenced in the filearchive table
	 *
	 * STUB
	 * @param array $storageKeys
	 */
	public function cleanupDeletedBatch( array $storageKeys ) {
		$this->assertWritableRepo();
	}

	/**
	 * Get a relative path for a deletion archive key,
	 * e.g. s/z/a/ for sza251lrxrc1jad41h5mgilp8nysje52.jpg
	 *
	 * @param string $key
	 * @throws MWException
	 * @return string
	 */
	public function getDeletedHashPath( $key ) {
		if ( strlen( $key ) < 31 ) {
			throw new MWException( "Invalid storage key '$key'." );
		}
		$path = '';
		for ( $i = 0; $i < $this->deletedHashLevels; $i++ ) {
			$path .= $key[$i] . '/';
		}

		return $path;
	}

	/**
	 * If a path is a virtual URL, resolve it to a storage path.
	 * Otherwise, just return the path as it is.
	 *
	 * @param string $path
	 * @return string
	 * @throws MWException
	 */
	protected function resolveToStoragePath( $path ) {
		if ( $this->isVirtualUrl( $path ) ) {
			return $this->resolveVirtualUrl( $path );
		}

		return $path;
	}

	/**
	 * Get a local FS copy of a file with a given virtual URL/storage path.
	 * Temporary files may be purged when the file object falls out of scope.
	 *
	 * @param string $virtualUrl
	 * @return TempFSFile|null Returns null on failure
	 */
	public function getLocalCopy( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getLocalCopy( array( 'src' => $path ) );
	}

	/**
	 * Get a local FS file with a given virtual URL/storage path.
	 * The file is either an original or a copy. It should not be changed.
	 * Temporary files may be purged when the file object falls out of scope.
	 *
	 * @param string $virtualUrl
	 * @return FSFile|null Returns null on failure.
	 */
	public function getLocalReference( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getLocalReference( array( 'src' => $path ) );
	}

	/**
	 * Get properties of a file with a given virtual URL/storage path.
	 * Properties should ultimately be obtained via FSFile::getProps().
	 *
	 * @param string $virtualUrl
	 * @return array
	 */
	public function getFileProps( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getFileProps( array( 'src' => $path ) );
	}

	/**
	 * Get the timestamp of a file with a given virtual URL/storage path
	 *
	 * @param string $virtualUrl
	 * @return string|bool False on failure
	 */
	public function getFileTimestamp( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getFileTimestamp( array( 'src' => $path ) );
	}

	/**
	 * Get the size of a file with a given virtual URL/storage path
	 *
	 * @param string $virtualUrl
	 * @return int|bool False on failure
	 */
	public function getFileSize( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getFileSize( array( 'src' => $path ) );
	}

	/**
	 * Get the sha1 (base 36) of a file with a given virtual URL/storage path
	 *
	 * @param string $virtualUrl
	 * @return string|bool
	 */
	public function getFileSha1( $virtualUrl ) {
		$path = $this->resolveToStoragePath( $virtualUrl );

		return $this->backend->getFileSha1Base36( array( 'src' => $path ) );
	}

	/**
	 * Attempt to stream a file with the given virtual URL/storage path
	 *
	 * @param string $virtualUrl
	 * @param array $headers Additional HTTP headers to send on success
	 * @return bool Success
	 */
	public function streamFile( $virtualUrl, $headers = array() ) {
		$path = $this->resolveToStoragePath( $virtualUrl );
		$params = array( 'src' => $path, 'headers' => $headers );

		return $this->backend->streamFile( $params )->isOK();
	}

	/**
	 * Call a callback function for every public regular file in the repository.
	 * This only acts on the current version of files, not any old versions.
	 * May use either the database or the filesystem.
	 *
	 * @param callable $callback
	 * @return void
	 */
	public function enumFiles( $callback ) {
		$this->enumFilesInStorage( $callback );
	}

	/**
	 * Call a callback function for every public file in the repository.
	 * May use either the database or the filesystem.
	 *
	 * @param callable $callback
	 * @return void
	 */
	protected function enumFilesInStorage( $callback ) {
		$publicRoot = $this->getZonePath( 'public' );
		$numDirs = 1 << ( $this->hashLevels * 4 );
		// Use a priori assumptions about directory structure
		// to reduce the tree height of the scanning process.
		for ( $flatIndex = 0; $flatIndex < $numDirs; $flatIndex++ ) {
			$hexString = sprintf( "%0{$this->hashLevels}x", $flatIndex );
			$path = $publicRoot;
			for ( $hexPos = 0; $hexPos < $this->hashLevels; $hexPos++ ) {
				$path .= '/' . substr( $hexString, 0, $hexPos + 1 );
			}
			$iterator = $this->backend->getFileList( array( 'dir' => $path ) );
			foreach ( $iterator as $name ) {
				// Each item returned is a public file
				call_user_func( $callback, "{$path}/{$name}" );
			}
		}
	}

	/**
	 * Determine if a relative path is valid, i.e. not blank or involving directory traveral
	 *
	 * @param string $filename
	 * @return bool
	 */
	public function validateFilename( $filename ) {
		if ( strval( $filename ) == '' ) {
			return false;
		}

		return FileBackend::isPathTraversalFree( $filename );
	}

	/**
	 * Get a callback function to use for cleaning error message parameters
	 *
	 * @return array
	 */
	function getErrorCleanupFunction() {
		switch ( $this->pathDisclosureProtection ) {
			case 'none':
			case 'simple': // b/c
				$callback = array( $this, 'passThrough' );
				break;
			default: // 'paranoid'
				$callback = array( $this, 'paranoidClean' );
		}
		return $callback;
	}

	/**
	 * Path disclosure protection function
	 *
	 * @param string $param
	 * @return string
	 */
	function paranoidClean( $param ) {
		return '[hidden]';
	}

	/**
	 * Path disclosure protection function
	 *
	 * @param string $param
	 * @return string
	 */
	function passThrough( $param ) {
		return $param;
	}

	/**
	 * Create a new fatal error
	 *
	 * @param string $message
	 * @return Status
	 */
	public function newFatal( $message /*, parameters...*/ ) {
		$status = call_user_func_array( array( 'Status', 'newFatal' ), func_get_args() );
		$status->cleanCallback = $this->getErrorCleanupFunction();

		return $status;
	}

	/**
	 * Create a new good result
	 *
	 * @param null|string $value
	 * @return Status
	 */
	public function newGood( $value = null ) {
		$status = Status::newGood( $value );
		$status->cleanCallback = $this->getErrorCleanupFunction();

		return $status;
	}

	/**
	 * Checks if there is a redirect named as $title. If there is, return the
	 * title object. If not, return false.
	 * STUB
	 *
	 * @param Title $title Title of image
	 * @return bool
	 */
	public function checkRedirect( Title $title ) {
		return false;
	}

	/**
	 * Invalidates image redirect cache related to that image
	 * Doesn't do anything for repositories that don't support image redirects.
	 *
	 * STUB
	 * @param Title $title Title of image
	 */
	public function invalidateImageRedirect( Title $title ) {
	}

	/**
	 * Get the human-readable name of the repo
	 *
	 * @return string
	 */
	public function getDisplayName() {
		global $wgSitename;

		if ( $this->isLocal() ) {
			return $wgSitename;
		}

		// 'shared-repo-name-wikimediacommons' is used when $wgUseInstantCommons = true
		return wfMessageFallback( 'shared-repo-name-' . $this->name, 'shared-repo' )->text();
	}

	/**
	 * Get the portion of the file that contains the origin file name.
	 * If that name is too long, then the name "thumbnail.<ext>" will be given.
	 *
	 * @param string $name
	 * @return string
	 */
	public function nameForThumb( $name ) {
		if ( strlen( $name ) > $this->abbrvThreshold ) {
			$ext = FileBackend::extensionFromPath( $name );
			$name = ( $ext == '' ) ? 'thumbnail' : "thumbnail.$ext";
		}

		return $name;
	}

	/**
	 * Returns true if this the local file repository.
	 *
	 * @return bool
	 */
	public function isLocal() {
		return $this->getName() == 'local';
	}

	/**
	 * Get a key on the primary cache for this repository.
	 * Returns false if the repository's cache is not accessible at this site.
	 * The parameters are the parts of the key, as for wfMemcKey().
	 *
	 * STUB
	 * @return bool
	 */
	public function getSharedCacheKey( /*...*/ ) {
		return false;
	}

	/**
	 * Get a key for this repo in the local cache domain. These cache keys are
	 * not shared with remote instances of the repo.
	 * The parameters are the parts of the key, as for wfMemcKey().
	 *
	 * @return string
	 */
	public function getLocalCacheKey( /*...*/ ) {
		$args = func_get_args();
		array_unshift( $args, 'filerepo', $this->getName() );

		return call_user_func_array( 'wfMemcKey', $args );
	}

	/**
	 * Get a temporary private FileRepo associated with this repo.
	 *
	 * Files will be created in the temp zone of this repo.
	 * It will have the same backend as this repo.
	 *
	 * @return TempFileRepo
	 */
	public function getTempRepo() {
		return new TempFileRepo( array(
			'name' => "{$this->name}-temp",
			'backend' => $this->backend,
			'zones' => array(
				'public' => array(
					// Same place storeTemp() uses in the base repo, though
					// the path hashing is mismatched, which is annoying.
					'container' => $this->zones['temp']['container'],
					'directory' => $this->zones['temp']['directory']
				),
				'thumb' => array(
					'container' => $this->zones['temp']['container'],
					'directory' => $this->zones['temp']['directory'] == ''
						? 'thumb'
						: $this->zones['temp']['directory'] . '/thumb'
				),
				'transcoded' => array(
					'container' => $this->zones['temp']['container'],
					'directory' => $this->zones['temp']['directory'] == ''
						? 'transcoded'
						: $this->zones['temp']['directory'] . '/transcoded'
				)
			),
			'hashLevels' => $this->hashLevels, // performance
			'isPrivate' => true // all in temp zone
		) );
	}

	/**
	 * Get an UploadStash associated with this repo.
	 *
	 * @param User $user
	 * @return UploadStash
	 */
	public function getUploadStash( User $user = null ) {
		return new UploadStash( $this, $user );
	}

	/**
	 * Throw an exception if this repo is read-only by design.
	 * This does not and should not check getReadOnlyReason().
	 *
	 * @return void
	 * @throws MWException
	 */
	protected function assertWritableRepo() {
	}

	/**
	 * Return information about the repository.
	 *
	 * @return array
	 * @since 1.22
	 */
	public function getInfo() {
		$ret = array(
			'name' => $this->getName(),
			'displayname' => $this->getDisplayName(),
			'rootUrl' => $this->getZoneUrl( 'public' ),
			'local' => $this->isLocal(),
		);

		$optionalSettings = array(
			'url', 'thumbUrl', 'initialCapital', 'descBaseUrl', 'scriptDirUrl', 'articleUrl',
			'fetchDescription', 'descriptionCacheExpiry', 'scriptExtension', 'favicon'
		);
		foreach ( $optionalSettings as $k ) {
			if ( isset( $this->$k ) ) {
				$ret[$k] = $this->$k;
			}
		}

		return $ret;
	}

	/**
	 * Returns whether or not storage is SHA-1 based
	 * @return boolean
	 */
	public function hasSha1Storage() {
		return $this->hasSha1Storage;
	}
}

/**
 * FileRepo for temporary files created via FileRepo::getTempRepo()
 */
class TempFileRepo extends FileRepo {
	public function getTempRepo() {
		throw new MWException( "Cannot get a temp repo from a temp repo." );
	}
}

redpajama_set_name: RedPajamaGithub


Another right he possesses over her is that she fulfils the duties of the household and that she does not unnecessarily make him hire a female servant, which may cause harm and due to which there will be a risk of danger for himself and his children.
"Those who say that it is obligatory for the woman to serve the husband use (this verse) as proof in that those who Allaah directed His Speech to (on this occasion) considered this to be from al-ma'roof (good). But as for the woman relaxing and having the husband serve her, sweep, grind the flour, knead the bread, wash the clothes, fix the bed, and serve the household, then that is from al-munkar (evil).
"For indeed Allaah obligated him to spend on her, to clothe her and to provide her with a place of dwelling in exchange for his enjoying her and her serving him, as well as what the habits of the spouses call for.
He is referring to Faatimah (radiyallaahu a'nhaa), for she would serve her husband diligently.
"Fear is a disease that consumes the soul of the one who embraces it. "


For the first time Barwick in Elmet has been selected by Yorkshire in Bloom as the "Best Village" in all the village categories, this discretionary award puts Barwick right at the top of the Yorkshire tree. This is a real compliment to the whole village effort and Barwick in Bloom would like to take this opportunity to thank the community on all levels for their continued generous support. Without the community support physical, financial and moral Barwick in Bloom could not exist, so a very big 'thank you' to all.
Both village churches have again been awarded Gold in Yorkshire in Bloom. The judges were very impressed by both church teams and described the Methodist gardens as a "glorious colourful vision" with great praise being heaped upon the All Saints team for their careful perennial planting and the dedicated effort needed to maintain weed free stone paths.
Tony Greaves received the "Community Champion" award at this year's Yorkshire in Bloom awards ceremony. Tony is a stalwart of Barwick in Bloom and the village community. Despite his advancing years he continues to do a tremendous amount for the local community. He has been a keen and very valued member of the Barwick in Bloom team since its inception 20 years ago and has been involved in almost everything which they have done. The "Bloom" team are thrilled that his efforts have been recognised in this way.


Daniel Lange is new Supply Chain Manager for Roth North Europe and his main focus will be on our logistics, service level to our customers and warehouse efficiency and optimizations.
<% } // only show image if set, alt text not required %> <p>Daniel has an solid educational background within Supply Chain Management. Furthermore, Daniel has a strong practical background within SCM and logistics and knows our business very well as he has worked many years in the industry in similar roles.


How much more can I take? Jerome wondered. This has been going on since high school and now I'm about to turn forty.
Mr. Wicks used to work for my father and now I have to work for him. It doesn't seem fair. I got the house and a healthy monthly stipend but he left the business to Mr. Wicks.
Jerome punched out and left and drove off the factory grounds without telling anyone. After all, he only had to sign in to work in order to get his monthly check and Wicks knew it and never hassled him about leaving early—just about sitting around doing nothing.
Jerome drove to the mall and wandered around, bought an Orange Julius, looked at the high school girls and left with more than he came with. Once home he went into the kitchen and unloaded his loot. Another watch, two jazz cds, a wedge of Chevre cheese, a three pack of tightly whiteys and two tubes of Crest toothpaste.
How much more can I take? Jerome wondered again as he looked around his house with unopened packages everywhere. And then he took out Mr. Wicks' Daytimer and letter opener from his briefcase along with a real treasure—Mr. Wick's library card.


I am building an application that dynamically renders the uis.
For this to happen, I thought of using the tool Sencha Architect 2 to give me the code I want ui. In applying make the request to the database that you want and the ui is rendered with the method Ext.applyIf.
I'll be doing the best?
Are you building complete forms based on selection, or by field? You mentioned using SA2, this leads me to believe you are offering which form to display?


Cadillac V-Net Discussion forums, pics, tech info, knowledgebase, etc., for all Cadillac V-series owners and enthusiasts!
Bottom line: GearWrench's small brake bleeder is a must have tool for the V-Net's DIY shop.
I've owned my ATS-V for two and a half years and almost 22,000 miles so, this week, it was time to flush the brakes. For over 20 years, when I've done brake work in my little DIY shop, I've used a small, hand-pumped, pressure bleeder, but recently, it malfunctioned so I replaced it.
The one I selected is from GearWrench (PN 2901D).This bleeder holds about a gallon of brake fluid, comes with a six-foot hose which on one end, has pressure gauge, a fluid shut-off valve and a quick-disconnect coupler. The tank has a pressure vent valve on the top next to the filler cap.
The fist step in using this tool is to install a brake bleeder adapter in place of the the master cylinder cap. Some of these are available from GrearWrench. If you use an adapter not made by GearWrench, such as the Kent-Moore J-35589A we use on our ATS-Vs, you have to install an automotive (also known as a Truflate, Type T, or C-style) air line coupler to the adapter. The GearWrench bleeder's quick disconnect goes onto the coupler on the adapter.
Filling the GearWrench pressure bleeder is as simple as unscrewing the top and pouring in several pints of brake fluid, in our case Red Line "RL-600". Several strokes of the GearWrench pressure bleeder's pump has it pressurized to 25-30-psi, the Service Manual's recommended pressure for bleeding. Pumping it up requires no more effort than pumping up a bike tire. Next, you open the valve at the end of the bleeder hose.
To flush the brakes on an ATS-V, you start at the right rear brake caliper. Since these are Brembo fixed-caliper brakes, each brake has two bleed fittings and you must bleed each of them individually. Remove the fitting caps then do the inner-most fitting first then the outer. When you open the fitting, the fluid will start coming out a medium brown color. After you close the fitting, replace the rubber fitting cap. I bleed each fitting until the fluid turns light yellow, indicative of fresh fluid. Then do the left front, left-rear and finally the right-front.
My new GearWrench brake bleeder works very well and is perfect for we DIY folks who are not bleeding brakes for a living and, thus, do not need a large, commercial-grade pressure bleeder. One feature the GearWrench bleeder has which my old one did not is the vent valve. I store the bleeder unpressurized. With my old bleeder, once I was done with it, I had to unscrew the top to release the pressure. It was always a challenge to unscrew the top slowly so the pressure would not release explosively. The GearWrench's vent valve makes venting pressure in the bleeder much easier.
For more information, see the GearWrench web site.
Hib Halverson works in automotive media, both print and Internet as a technical writer. He is the Lead Product Evaluator for the V-Net and its sister web site, the Corvette Action Center. Hib owns two 2016 ATS-Vs, a six-speed Coupe and an eight-speed Sedan.


In the age of the internet and due to the changing economic conditions involving globalization with a major shift to using technology in the workplace, more and more people are searching for legitimate work from home online jobs. The good news is the opportunities are vast for doing both conventional and modern work.
In this article, I will begin by offering you some ideas for the more traditional approach to finding an online job. I will touch on being a writer, translator, book-keeper and web designer. There are many more. As a matter of fact, I would say almost any conventional kind of work can be brought online these days providing you with an opportunity to work from home.
The last part of this post will let you know what modern skills you can develop while using them to develop a valid, legal online business working from your home or anywhere in the world. I belong to this latter group of people. A fast-growing group of like-minded solopreneurs taking control of their work, life and financial security.
There are many opportunities for talented writers to work from home. Writers are in demand to create the content for blog posts, web pages, and social media posts. They also produce white papers, e-books, press releases, and detailed guides.
Work-at-home writers may have specialized education or experience that uniquely qualifies them for the job, but often they merely need fluency in the language and the ability to write.
Freelance writers can find work through websites that have freelance writing jobs or gigs, they can work for sites that offer writing services to their clients, they can work as traditional writers selling articles to news outlets or magazines, or they can even work genuinely independently as bloggers or authors of e-books.
In 2015, full-time freelance writers earned a median income between $20K – 30K per year. That is significantly less than the median wage in the US that year, but freelance writers work for rates across the spectrum, from less than a penny per word to hundreds of dollars an article. Writers who find a good niche and good clients can earn significantly more.
For those who are fluent in two or more languages, translation services are in high demand around the world. Because countries grow more connected, there is more need than ever for documents, entertainment, websites, games, and content to be provided in multiple languages.
The explosion of social media and online video, where many people prefer to watch or share video content without audio, has led to an ever-growing need for all content to be localized and all video content to be captioned in the language specified in the user settings, for every piece of content created and shared online.
These freelancers can work at home either as freelancers, finding clients or gigs through freelance job sites, or through specialized translation job sites. They often need to pass skills or proficiency tests to get listed on these sites or to have their translations approved by a supervisor during a trial period. These freelancers can also specialize in specific skills, like technical or medical language translation.
According to the American Translators Association, US-based freelance translators earned an average of $45K/year in 2015 if they were not ATA certified, and certified freelance translators earned an average of $54K/year. Obviously, with that kind of disparity, it's worth it for a US-based translator to get ATA certified, but not necessary. Good translators with an excellent reputation and strong self-marketing often earn more than six figures.
Bookkeeping and accounting are jobs that are well-suited to work-at-home online freelancers because they often don't require much direct human communication and can be done outside of office hours. Online bookkeepers are also a good solution for small businesses, who often don't need and can't afford a full-time staff person, or don't have room in their office for another employee. An online freelance bookkeeper will record transactions for accounts payable, accounts receivable, or payroll. They manage data entry, maintain accurate records, and can monitor budgets or inventories.
While a bookkeeper is primarily concerned with ensuring that math and records are accurate and up to date and often doesn't need specialized skills besides accurate data entry and some experience, an accountant requires higher education and certification. An accountant is better equipped to provide financial advice, oversight, and strategy in partnership with company leadership. Of course, freelance accountants charge higher rates, and their jobs often involve a higher degree of real-time communication and collaboration than a bookkeeper's job.
Bookkeeping services are in high demand because it's a service that every business requires, but many small business owners are too busy or too inaccurate to do the work themselves. Like translators, freelance bookkeepers can find work on freelance job sites and boards, or through specialized sites that provide virtual bookkeeping services to their clients. They can also work with online accounting services sites, which provide combined accounting and bookkeeping services to their clients, and often these specialty sites pay the best rates.
Full-time staff bookkeepers usually start at over $18/hour, depending on experience, and earn an average of $40K/year. Working online and remotely often means the ability to charge a higher hourly rate, but usually means not working full time unless you can find and balance multiple clients, so there is a wide range of possible earnings.
With the ubiquity of WordPress and the ease of using their themes, you might think that web design is no longer in as high a demand as it was. However, people's expectations for online experiences keep growing, leading to more advanced customization, creative solutions, and tailor-made designs. Web design is as strong as it's ever been, and freelance work from home web designers have an excellent future outlook.
Web designers often have a lot of formal and informal education, and they need to have experience in a variety of specialized software, with particular attention to the Adobe Suite, including Photoshop and InDesign. It's also helpful for them to know at least the basics of how to code a website, including HTML and CSS because they need not only to plan how the design looks but ensure that the design works. They need to understand SEO and user experience as well as visual design.
To top it all off, they have to have excellent people skills, because they will be entrusted with creating a design that works for their client as well as for their client's site visitor. Because of the number and complexity of skills involved, formal education can be helpful, but it's not strictly necessary if you have the skills and the portfolio to prove it. Web designers often specialize in particular areas or industries, including online scheduling, databases, e-commerce, social media integration, and more.
In the US, freelance web designers earn an average of $64K/year, but specialists and those working with high-end clients can receive much more than that.
All the above ideas are legitimate work from home online jobs. There is no question that they will supply you with a stable income to provide for yourself and your family. The problem is you are trading time for money. Your ultimate goal should be to use your money and time wisely to make money.
This is a process and the very rich know that. We all need to start somewhere. Doing writing gigs will not get you there. You need to take it a step further – maybe write a best-selling book. Something which can be sold over and over again once the original work is done thus providing you with a steady passive income.
The top 1% invest in real estate. Large buildings that pay for themselves and bring in huge returns. That is steady streams of "passive income". We are not in a position to do this right now because we need more cash flow. In the example above becoming a best-selling author would give you the necessary resources to become truly independent financially.
However, there is also another way. A path thousands of others have taken and are quietly turning into an online revolution. Folks are seizing control of their financial future by starting legitimate online businesses. They are doing so well that the governments of the top economies around the world have implemented taxes to cash in on their success.
I am a part of this revolution. I have one of these legitimate online work from home jobs and my goal is to eventually turn it into a steady stream of passive income allowing me to leave the lifestyle I wish. This is my project – projekt freedom. I am talking about doing affiliate marketing, email marketing, or e-commerce marketing online.
Basically, you are selling items on the internet. There are different business models which you can choose from but the results or end goal is the same. You do the work once and you reap the rewards for decades to come. Like anything in life, you need to learn the skills, apply them and finally enjoy the benefits.
In my case, I have a blog. I try to write quality content. Google learns to trust my site and rewards me with high rankings which in turn sends visitors to my site. The readers who find my writings compelling will make a purchase. I only do the work once but I can get repeat sales for years to come.
In time, (I have already started) I can outsource the writing and other tasks allowing my business to scale up at an amazing rate. Once this happens the sky is the limit because the cash flow is available to invest in real estate. Mike Dillard was able to accomplish this in a few short years.
I recommend you take your present unique abilities (such as the ones above) and turn it into a thriving online business selling a service or products. The skills you lack will be acquired along the way while you are establishing the business. The overhead is minimal and actually, in many cases, it is free to get started.


It will be pretty close.. I know our cars are only worth 2k, or just over that.
For a new fender, bumper cover, corner light, fixing the hood... You're at 1k right there.
IF by some chance they totalled it, I'd for sure buy it back and fix it. It's not bad enough to leave it with them and have it go for scrap.
This has got me so upset, lol. I just put an exhaust on it and got springs in the mail too. I'm just scared that a new fender won't properly align. I can go to pull a part and source everything I need for 100-200 dollars so this just makes me sad.
Good news came in!!! Not only is insurance not totalling it, they gave me 2k from the estimate I got and I opted to fix it myself, looks like I'm going to get a fresh coat of paint.
Lucky, same thing happened to mine. I didn't do n e thing to the exterior yet but I put two new axles, ball joints, manual rack, and a jdm b20.
Glad that there is NOT one more DA taken off of the streets man!
Here are some pictures after mostly fixing the damages, I will probably get it painted in early spring ,although I still need a new bumper cover.
Last edited by Blake93da; 12 Feb 2014, 23:24:41.
Do you have a picture of the driver side?
driver side lines up good I just have a white fender from a 91 ls I scored at pull a part. I only have a couple of pics of that side when I was installing the headlights.
Here is a better pic of the driver side.
All times are GMT. This page was generated at 21:12:11.


text:
Reversal theory sports psychology. Reversal theory 2019-01-09
Reversal theory sports psychology Rating: 7,5/10 1439 reviews
Reversal theory
Makes distinctions between competitive state cognitive anxiety on the premise that they have different relationships to performance. For example, an ice hockey player who is optimally aroused would have an elevated heart rate, increased beta waves, increased respiration, and increased adrenalin. They are always anxious with doing everyday things. The next round he relaxed his body and ended up giving some hard punches which won him the fight. It has been seen that exercise and increased fitness seem to improve these individuals health. This is because they tend to take a single value and encourage us to organize our life around this value alone.
Arousal in Sport Research Paper Example
History, Use and Instrumentation Reversal Theory was first proposed in the mid-1970s, by K. They are each associated with their own range of emotions. It will be seen from this that reversal theory gives a very different interpretation of arousal from optimal arousal theory, with its famous inverted u-curve. Somatic anxiety is predicted to display an inverted-U relationship with performance and cognitive anxiety a negative linear relationship. In optical illusions involving apparent movement, for example, that movement is not detected. The more confident you are the more likely you will be a eustress instead of destress. This is a video of a footballer playing in the world cup final and has a great chance of winning the world cup, but does something silly by headbutting another player which sends him off and costs him and his country the world cup.
Motivation and Emotion in Sport: Reversal Theory, 1st Edition (Paperback)
Is there a source of emotions that is stable within us? The physiological component of arousal can be represented in a number of ways such as through muscle tension, cortical activity, electrodermal activity, respiration, and biochemical markers e. State : State is a learned behavior response. Sometimes a crying baby creates sympathy; other times it causes irritation. It focuses on the dynamic qualities of normal human experience to describe how a person regularly reverses between psychological states, reflecting their motivational style and the meaning they attach to a given situation at a given time. It was first formulated by British psychologist in 1970s. It can come genetically and picked up on. In addition, suggestions as to alications of reversal theory in new areas of sport psychology and the future direction of reversal theory-based sport research are outlined.
Reversal theory: A suggested way forward for an improved understanding of interpersonal relationships in sport
Here is an indicator, a red flag, that should tell the reader to be aware of theories, lest they become the latest fad in pop psychology and leadership. To re-join the curve, the athlete needs to completely relax both psychologically and physiologically and gain control over their negative thoughts and arousal. For example, a participant in a study may experience the study as a kind of game on one occasion in the paratelic state and as serious on another in the telic state. This assists in understanding the emotions felt by athletes when they are injured as emotions, such as humility, may not be regularly understood by persons other than the injured athlete Thatcher et al. Physiologically, modalities measurable through psychophysiological monitoring, such as brain waves, skin conductance, heart rate, blood pressure, and muscle tension, all are elevated when an individual is aroused. Assess psychological strengths and weaknesses. This happened because he was over aroused which meant that he was only focusing on the big picture and not the little things which cost him the match.
Motivation and emotion in sport reversal theory (Book, 1997) [hueygrov.es]
Specific areas for future research are identified. Using these tools, investigations have been conducted which have largely supported the telic-paratelic model which has just been presented, and favoured it over other accounts. Biofeedback This is because the player is playing well alll of his tricks are working and his body is working together with his mind. Second, how do we validate that one indeed is having such a state? The theory has in this way generated over 200 publications, including nine books. State anxiety is reduced once the stressor has been removed e. Motivation and Emotion, 6, 3, 193-215. In this state, one focuses more on the activity they are undertaking rather than the goal they trying to achieve and as such, arousal is interpreted as a pleasant experience of excitement where the enjoyment of the activity is increased Martin et al.
sports psychology:P4 Arousal theories by on Prezi
Emotion and Stress in Serious and Hedonistic Leisure Sport Activities, Journal of Leisure Research, 34 3 , 272-289. Whereas combinations within the mastery-sympathy and autic-alloic states result in transactional emotions such as pride, modesty, gratitude, virtue, humiliation, shame and guilt Kerr, 2009. For example, sometimes a roller coaster seems exciting; other times, it may cause anxiety. What happens when arousal exceeds optimal level? Some researchers have even gone so far as to been closely associated with the concept of social facilitation, some have questioned whether the arousal—performance relationship depicted exists in all motor activities required in sport. The effect of this is that an individual can be in the same situation at different times, but experience it differently - and therefore behave in it differently too. Cognitive is a mental aspect.
Reversal theory's systematic conceptual framework allows a unique perspective for interpreting behaviour in sport contexts. Counselling Athletes is essential reading for all practising sport psychologists and coaches, and for any student of sport psychology. For example, anxiety is assumed by some to be always bad. Three prominent theories of arousal in sport are drive theory, the inverted-U hypothesis, and reversal theory. The two types of stress are tension and effort stress Thatcher et al. They give some order to our lives, some meaning , and some direction.
This is because his arousal level was low which means that he is tired and wasn't prepared, this is why he made the mistake. Using my volleyball example in college. Opponent-process states that a stimulus creates an opposite effect once the stimulus is removed, as in a stimulus creating an anxiety creates the feeling of relief once the stimulus is removed. Rethinking the script: Future directions in reversal theory sports research and practice -- App. Likewise for the other three pairs of motivational states posited in the theory. London and New York: Academic Press.
Introduction to Reversal Theory
Reversal Theory links the motivational states above to emotion by proposing that if one is in a state and things are going well, positive emotions result; if the needs of the state are not fulfilled, negative emotions result. We respond to the same situations in the same way when we encounter them. Metamotivation colors the whole of experience at a given time, and these colors keep changing. Emotional control positive self talk This is positive self talk because after the player has slipped he needs to get over it and find away to motivate himself. Self-talk or the use of cue words can energize i.

redpajama_set_name: RedPajamaCommonCrawl


"White roads" (that's the colour on the map) are D-roads, so are "yellow roads", but I like white roads better because there is less traffic. Somtimes this means more distance but that's OK.
There are so few bends in this part of France that every one is signposted – that would cost a fortune in Austria. There are plenty of vertical bends – that of course means uphills and downhills. You can see a long way and know that after the exhilerating downhill ride you must keep enough momentum and change gear in time to get up the other side! it's like the wine quarter of lower Austria – all the villages are at the bottom of the hill and you have to go up afterwards!
Wir sind beindruckt uns wünschen weiterhin viel Spass.
Wir waren eine Woche in Zadar mit Werner und Zdenka. Das Wetter und das Wasser war schön. Grüße von Werner und Zdenka.


A basic stairlift design, offering an economy option with many of our best features.
The Scout stairlift gets you from A to B, utilizing many of the key features and proven components from our Siena and Starla chairs. While the Scout is our economy model stairlift, with Stannah, you can always count on a safe and reliable ride.
Give us your name and number and we'll call you within 24 hours.
Request your brochure today, commitment-free.
Request your free quote now.
What do you get from your Scout?
A well-designed, economy model stairlift. The Scout utilizes our basic comfort and safety features to provide you with an affordable way to enjoy the full use of your home.
Each and every one of our stairlifts is built to meet your needs. As you explore our range you can see the unique features of each of our stairlifts, and how they were built to help with your daily living. The Scout was designed as an affordable alternative for straight stairs, where mobility issues are minimal and the enhanced features of the Siena and Starla chairs are not required.
While many of our other models offer customizable options like upholstery choices and powered swivel seats, the Scout is a great option if you're looking for a basic, low cost stairlift.
The Scout is fitted with batteries, so it will never let you down in a power outage.
The Scout glides smoothly, quietly, up or down your stairs at the push of a lever.
The Scout swivels onto the top landing and locks into place, acting as a barrier as you exit the chair.
The Scout is fitted with a center-clasp seatbelt.
The Scout comes with vinyl upholstery for easy cleaning.
The Scout comes with remote controls for the top and bottom of the stairs.
The Scout is equipped with safety sensors. If there's anything in its path, it'll come to a gentle stop.
The controls are easy to use. Use your hand or wrist to push in the direction you want to go and you're safely on your way.
See all our stairlift models for different types of stairs.
Have a look at all the different models of Stannah stairlifts we offer for your stairs. Find out which model best suits your needs.
Would you rather we sent you a free brochure?
While the Scout was primarily designed as a basic stairlift option, it still maintains many important features of the Stannah line. Take a look at what makes the Scout such an intriguing option.
The Scout's slim profile means it can fit into tight staircases and swivel onto upper landings with a door at the top, even if space is limited. That makes it a great fit for basement stairs and garage entries.
The Scout's footrest carpeting prevents slips when getting in and out of the chair. So, you can always feel confident stepping onto the sturdy footrest. The footrest also can be folded away when the stairlift is not in use.
The Scout has safety sensors on the side of the carriage and beneath the footrest, which means it will stop if it encounters an obstruction. You'll never get your foot caught or run over anything while riding your stairlift.
The Scout is operated by an intuitive, ergonomic hand control which can be operated with any part of the hand or wrist. It also comes with two remote controls, allowing you to call it from another floor.
For maximum comfort and safety, the seat of the Scout can be adjusted to your height during installation. We'll make sure everything is positioned perfectly, so you'll never have to worry about it!
The Scout is fitted with a diagnostic window on the carriage, below the seat. If you make a mistake, you can easily troubleshoot the problem using the number code in the window. We'll give you a key for the codes during installation.


text:
Riems
Riems Explained
Native Name: Insel Riems
Map: Germany
Location: Baltic Sea
Coordinates: 54.1833°N 13.3667°W
Total Islands: 1
Length M: 300
Width M: 1250
Riems is an island in the southwestern part of the Bay of Greifswald, a broad, shallow embayment of the Baltic Sea between the German mainland and the island of Rügen. Riems belongs administratively to the urban district of Greifswald, but is an exclave. Riemserort, is municipally part of Riems, but lies opposite the island on the mainland.
The island of Riems measures about 1,250 metres from east to west, and is about 300 metres across at its widest point. Since the early 1970s, it has been connected to the mainland by a 500m long causeway. It has, therefore, been an artificial peninsula for more than 30 years. Before the causeway, a cable car used to transport goods to the mainland. The cable car has now gone, but the ruins of its pylon foundations are still visible. Because the lack of fresh water to the Gristower Wiek resulted in oxygen depletion in the shallow bay, in the autumn of 2007 a 30-metre-long section of the causeway to the island was opened and bridged to allow fresh water to pass once more.
Riems is an important resting and moulting area for waterbirds. The Fahrenbrink Peninsula Nature Reserve (German: Naturschutzgebiet Halbinsel Fahrenbrink) is a recognized reserve. Approximately 15 percent of the northern European waterfowl population spend their winter in the area of the Bay of Greifswald and the Strelasund. It has therefore been declared a European bird reserve.
Riems has been inhabited since prehistoric times as Stone Age and Slavic archaeological finds demonstrate. The island later belonged, together with the adjacent village of Gristow, to the family of Dotenberg. Between 1375 and 1382, Riems and Gristow became the possession of the city of Greifswald, which leased the then uninhabited island out as pasture land. After 1820, the city built a homestead but sold it back to its previous tenant in 1883.
Riems is home to the oldest virological research institution in the world, now called the Friedrich Loeffler Institute, which was built by Friedrich Loeffler in 1910. Loeffler, a professor at the University of Greifswald, ran filtration tests in 1898 and found that the dangerous foot-and-mouth disease was not a bacterium, but a previously unknown class he called "the smallest of all organisms". He had determined it to be a virus. After investigations showed that Loeffler had inadvertently infected the whole region of Greifswald with foot-and-mouth disease he moved to the safer location of his institute on the island of Riems in 1910.
The Third Reich used the institute in Riems to research bioweapons.[1]
While East Germany controlled Riems approximately 800 people were working on vaccine research and development, today there are less than half that number. The population on the island is quite small. There are only 13 houses, five one-or two-family homes and eight apartment buildings, with a total of 62 residential units.
Since 1997, the research complex is the headquarters of the Riemser Friedrich-Loeffler-Institute (FLI). The duties of the FLI include research on animal diseases, such as Bovine spongiform encephalopathy, foot-and-mouth disease and swine fever, and the development of preventive and protective measures against it, especially veterinary vaccines. As of 2006, Riems was working on a vaccine for the avian flu. By 2010, the Institute was to reduce their current locations Tübingen, Wusterhausen and Jena to just Jena and Riems. The total budget for the expansion work is some 150 million €. The construction needed to be handled carefully because of the historically rich old buildings.
The former production plant for animal vaccines was successfully privatized as Riemser Arzneimittel AG. It has about 150 employees.
After the 1990s the populated area in the western part of the island was freely accessible for some years. However, because of the renewed research work with viruses the island is again closed to the public. Quarantine stables and laboratories security levels are Level 4. This means employees and visitors to the complex must change their clothes, and shower, when entering and exiting.
Erich Traub
Kurt Blome
http://www.wassersport-im-bodden.de/
Erhard Geißler: Hitler und die Biowaffen.. Lit, : S. 123 "... es sei gelungen, Rinder durch Versprühen eines in der Reichsforschungsanstalt Insel Riems hergestellten Viruspräparates ... mit MKS zu infizieren." (Google Books)
This article is licensed under the GNU Free Documentation License. It uses material from the Wikipedia article "Riems".


The Cherokee peoples' religious views of fire and the sun are analyzed. The article uses the observations of Cherokee religious practices observed and written by Alexander Longe in 1725, James Adair in 1775, and John Howard Payne and Dr. Samuel Butrick between 1825 and 1840. The observations discuss the fire and sun cults within Cherokee religious practices.


The presentation will focus on the policies behind mediator licensing and certification, and the early efforts of the dispute resolution community in Arizona to "professionalize" the practice of mediation.
Most of Bob Dauber's teaching energies are devoted to supervising and instructing student attorneys in Sandra Day O'Connor College of Law's Civil Justice Clinic. He also regularly teaches courses relating to civil procedure, professionalism and dispute-resolution processes. Professor Dauber's research interests include court-connected mediation and other forms of dispute resolution, and he regularly presents papers and workshops on Alternative Dispute Resolution-related topics. Professor Dauber's most recent articles have related to empirical studies of court-connected mediation and arbitration.
Professor Dauber helped design the Lodestar Mediation Clinic, a course offering in which law students receive intensive skills training and practical experience in the mediation process, while studying the theoretical foundations of ADR. He is a former director of the mediation clinic and also has served as the interim director of the college's Clinical Program. Before joining the clinical faculty in 1990, he practiced for seven years as a trial attorney with the Phoenix office of Winston & Strawn.
Professor Dauber has served on the boards of directors for Community Legal Services, the Arizona Dispute Resolution Association, the Homeless Legal Assistance Project and the Capital Representation Project, and on the ADR Advisory Board to the Supreme Court of Arizona.