kimoi/MangaIndex — pull request #1 by fake-name (2014-09-14 09:47:02+00:00)
Title: Added intelligent sorting that attempts to extract volume&chapter info, and preferentially sort by that.

Ok, first things first, **I'm not totally confident this is valid PHP**. I don't have PHP installed anywhere.

Anyways, this is a rough replica of [something I have implemented](https://github.com/fake-name/MangaCMS/blob/master/ctnt/reader2/render.mako#L76) in my own manga reader project.

Basically, the idea is to, when possible, extract the chapter & volume information from a filename, and preferentially sort by that. It works very well in my implementation.

Given a arbitrary directory contents:
```
Folder items
File -> 'Pygmalio episode02 c25[WingtipCafe].zip'
File -> 'Pygmalio v01 c01-13 + Omake.zip - Pygmalio v01 c01-13 + Omake.zip'
File -> 'Pygmalio v04 c40-53 + Omake.zip - Pygmalio v04 c40-53 + Omake.zip'
File -> 'Pygmalio episode02 c24[WingtipCafe].zip'
File -> 'Pygmalio v02 c10[Wingtip Cafe].zip'
File -> 'Pygmalio v03 c17[WingtipCafe].zip'
File -> 'Pygmalio episode02 c27[WingtipCafe].zip'
File -> 'Pygmalio - v8 c97.zip'
File -> 'Pygmalio v03 c08-16[WingtipCafe].zip'
File -> 'Pygmalio - v7 c92.zip'
File -> 'Pygmalio episode02 c26[WingtipCafe].zip'
File -> 'Pygmalio episode02 c20[WingtipCafe].zip'
File -> 'Pygmalio - c91 - 91.zip'
File -> 'Pygmalio - c90 - 90.zip'
File -> 'Pygmalio v02 c14-26 + Omake.zip - Pygmalio v02 c14-26 + Omake.zip'
File -> 'Pygmalio - c89 - 89.zip'
File -> 'Pygmalio - v7 c93.zip'
File -> 'Pygmalio - v8 c96.zip'
File -> 'Pygmalio v01[Wingtip Cafe].zip'
File -> 'Pygmalio episode02 c23[WingtipCafe].zip'
File -> 'Pygmalio - v7 c90.zip'
File -> 'Pygmalio - 85 - pygmalio_85.zip'
File -> 'Pygmalio - v8 c95.zip'
File -> 'Pygmalio - 84 - pygmalio_84.zip'
File -> 'Pygmalio v05 c54-67 + Omake.zip - Pygmalio v05 c54-67 + Omake.zip'
File -> 'Pygmalio - v7 c88.zip'
File -> 'Pygmalio - 86 - pygmalio_86.zip'
File -> 'Pygmalio v04 c21[WingtipCafe].zip'
File -> 'Pygmalio - v8 c94.zip'
File -> 'Pygmalio - 81 - pygmalio_81.zip'
File -> 'Pygmalio v03 c27-39 + Omake.zip - Pygmalio v03 c27-39 + Omake.zip'
File -> 'Pygmalio v03 c19[WingtipCafe].zip'
File -> 'Pygmalio v03 c18[WingtipCafe].zip'
File -> 'Pygmalio - v7 c91.zip'
File -> 'Pygmalio v06 c68-80 + Omake.zip - Pygmalio v06 c68-80 + Omake.zip'
File -> 'Pygmalio - v7 c87.zip'
File -> 'Pygmalio - 83 - pygmalio_83.zip'
File -> 'Pygmalio - v7 c89.zip'
File -> 'Pygmalio - 82 - pygmalio_82.zip'
```

Preprocess to:
```
Preprocessed items
Item -> '(0.0, 25.0, 'Pygmalio episode02 c25[WingtipCafe].zip')'
Item -> '(0.0, 1.0, 'Pygmalio v01 c01-13 + Omake.zip - Pygmalio v01 c01-13 + Omake.zip')'
Item -> '(0.0, 40.0, 'Pygmalio v04 c40-53 + Omake.zip - Pygmalio v04 c40-53 + Omake.zip')'
Item -> '(0.0, 24.0, 'Pygmalio episode02 c24[WingtipCafe].zip')'
Item -> '(0.0, 10.0, 'Pygmalio v02 c10[Wingtip Cafe].zip')'
Item -> '(0.0, 17.0, 'Pygmalio v03 c17[WingtipCafe].zip')'
Item -> '(0.0, 27.0, 'Pygmalio episode02 c27[WingtipCafe].zip')'
Item -> '(0.0, 97.0, 'Pygmalio - v8 c97.zip')'
Item -> '(0.0, 8.0, 'Pygmalio v03 c08-16[WingtipCafe].zip')'
Item -> '(0.0, 92.0, 'Pygmalio - v7 c92.zip')'
Item -> '(0.0, 26.0, 'Pygmalio episode02 c26[WingtipCafe].zip')'
Item -> '(0.0, 20.0, 'Pygmalio episode02 c20[WingtipCafe].zip')'
Item -> '(0.0, 91.0, 'Pygmalio - c91 - 91.zip')'
Item -> '(0.0, 90.0, 'Pygmalio - c90 - 90.zip')'
Item -> '(0.0, 14.0, 'Pygmalio v02 c14-26 + Omake.zip - Pygmalio v02 c14-26 + Omake.zip')'
Item -> '(0.0, 89.0, 'Pygmalio - c89 - 89.zip')'
Item -> '(0.0, 93.0, 'Pygmalio - v7 c93.zip')'
Item -> '(0.0, 96.0, 'Pygmalio - v8 c96.zip')'
Item -> '(1.0, 0.0, 'Pygmalio v01[Wingtip Cafe].zip')'
Item -> '(0.0, 23.0, 'Pygmalio episode02 c23[WingtipCafe].zip')'
Item -> '(0.0, 90.0, 'Pygmalio - v7 c90.zip')'
Item -> '(0.0, 85.0, 'Pygmalio - 85 - pygmalio_85.zip')'
Item -> '(0.0, 95.0, 'Pygmalio - v8 c95.zip')'
Item -> '(0.0, 84.0, 'Pygmalio - 84 - pygmalio_84.zip')'
Item -> '(0.0, 54.0, 'Pygmalio v05 c54-67 + Omake.zip - Pygmalio v05 c54-67 + Omake.zip')'
Item -> '(0.0, 88.0, 'Pygmalio - v7 c88.zip')'
Item -> '(0.0, 86.0, 'Pygmalio - 86 - pygmalio_86.zip')'
Item -> '(0.0, 21.0, 'Pygmalio v04 c21[WingtipCafe].zip')'
Item -> '(0.0, 94.0, 'Pygmalio - v8 c94.zip')'
Item -> '(0.0, 81.0, 'Pygmalio - 81 - pygmalio_81.zip')'
Item -> '(0.0, 27.0, 'Pygmalio v03 c27-39 + Omake.zip - Pygmalio v03 c27-39 + Omake.zip')'
Item -> '(0.0, 19.0, 'Pygmalio v03 c19[WingtipCafe].zip')'
Item -> '(0.0, 18.0, 'Pygmalio v03 c18[WingtipCafe].zip')'
Item -> '(0.0, 91.0, 'Pygmalio - v7 c91.zip')'
Item -> '(0.0, 68.0, 'Pygmalio v06 c68-80 + Omake.zip - Pygmalio v06 c68-80 + Omake.zip')'
Item -> '(0.0, 87.0, 'Pygmalio - v7 c87.zip')'
Item -> '(0.0, 83.0, 'Pygmalio - 83 - pygmalio_83.zip')'
Item -> '(0.0, 89.0, 'Pygmalio - v7 c89.zip')'
Item -> '(0.0, 82.0, 'Pygmalio - 82 - pygmalio_82.zip')'
```
Perform sort on processed array,
```
Sorted items
Item -> '(0.0, 1.0, 'Pygmalio v01 c01-13 + Omake.zip - Pygmalio v01 c01-13 + Omake.zip')'
Item -> '(0.0, 8.0, 'Pygmalio v03 c08-16[WingtipCafe].zip')'
Item -> '(0.0, 10.0, 'Pygmalio v02 c10[Wingtip Cafe].zip')'
Item -> '(0.0, 14.0, 'Pygmalio v02 c14-26 + Omake.zip - Pygmalio v02 c14-26 + Omake.zip')'
Item -> '(0.0, 17.0, 'Pygmalio v03 c17[WingtipCafe].zip')'
Item -> '(0.0, 18.0, 'Pygmalio v03 c18[WingtipCafe].zip')'
Item -> '(0.0, 19.0, 'Pygmalio v03 c19[WingtipCafe].zip')'
Item -> '(0.0, 20.0, 'Pygmalio episode02 c20[WingtipCafe].zip')'
Item -> '(0.0, 21.0, 'Pygmalio v04 c21[WingtipCafe].zip')'
Item -> '(0.0, 23.0, 'Pygmalio episode02 c23[WingtipCafe].zip')'
Item -> '(0.0, 24.0, 'Pygmalio episode02 c24[WingtipCafe].zip')'
Item -> '(0.0, 25.0, 'Pygmalio episode02 c25[WingtipCafe].zip')'
Item -> '(0.0, 26.0, 'Pygmalio episode02 c26[WingtipCafe].zip')'
Item -> '(0.0, 27.0, 'Pygmalio episode02 c27[WingtipCafe].zip')'
Item -> '(0.0, 27.0, 'Pygmalio v03 c27-39 + Omake.zip - Pygmalio v03 c27-39 + Omake.zip')'
Item -> '(0.0, 40.0, 'Pygmalio v04 c40-53 + Omake.zip - Pygmalio v04 c40-53 + Omake.zip')'
Item -> '(0.0, 54.0, 'Pygmalio v05 c54-67 + Omake.zip - Pygmalio v05 c54-67 + Omake.zip')'
Item -> '(0.0, 68.0, 'Pygmalio v06 c68-80 + Omake.zip - Pygmalio v06 c68-80 + Omake.zip')'
Item -> '(0.0, 81.0, 'Pygmalio - 81 - pygmalio_81.zip')'
Item -> '(0.0, 82.0, 'Pygmalio - 82 - pygmalio_82.zip')'
Item -> '(0.0, 83.0, 'Pygmalio - 83 - pygmalio_83.zip')'
Item -> '(0.0, 84.0, 'Pygmalio - 84 - pygmalio_84.zip')'
Item -> '(0.0, 85.0, 'Pygmalio - 85 - pygmalio_85.zip')'
Item -> '(0.0, 86.0, 'Pygmalio - 86 - pygmalio_86.zip')'
Item -> '(0.0, 87.0, 'Pygmalio - v7 c87.zip')'
Item -> '(0.0, 88.0, 'Pygmalio - v7 c88.zip')'
Item -> '(0.0, 89.0, 'Pygmalio - c89 - 89.zip')'
Item -> '(0.0, 89.0, 'Pygmalio - v7 c89.zip')'
Item -> '(0.0, 90.0, 'Pygmalio - c90 - 90.zip')'
Item -> '(0.0, 90.0, 'Pygmalio - v7 c90.zip')'
Item -> '(0.0, 91.0, 'Pygmalio - c91 - 91.zip')'
Item -> '(0.0, 91.0, 'Pygmalio - v7 c91.zip')'
Item -> '(0.0, 92.0, 'Pygmalio - v7 c92.zip')'
Item -> '(0.0, 93.0, 'Pygmalio - v7 c93.zip')'
Item -> '(0.0, 94.0, 'Pygmalio - v8 c94.zip')'
Item -> '(0.0, 95.0, 'Pygmalio - v8 c95.zip')'
Item -> '(0.0, 96.0, 'Pygmalio - v8 c96.zip')'
Item -> '(0.0, 97.0, 'Pygmalio - v8 c97.zip')'
Item -> '(1.0, 0.0, 'Pygmalio v01[Wingtip Cafe].zip')'
```
and then a list-comprehension that retreives just the filenames:

```
Sorted fileNames
Item -> 'Pygmalio v01 c01-13 + Omake.zip - Pygmalio v01 c01-13 + Omake.zip'
Item -> 'Pygmalio v03 c08-16[WingtipCafe].zip'
Item -> 'Pygmalio v02 c10[Wingtip Cafe].zip'
Item -> 'Pygmalio v02 c14-26 + Omake.zip - Pygmalio v02 c14-26 + Omake.zip'
Item -> 'Pygmalio v03 c17[WingtipCafe].zip'
Item -> 'Pygmalio v03 c18[WingtipCafe].zip'
Item -> 'Pygmalio v03 c19[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c20[WingtipCafe].zip'
Item -> 'Pygmalio v04 c21[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c23[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c24[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c25[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c26[WingtipCafe].zip'
Item -> 'Pygmalio episode02 c27[WingtipCafe].zip'
Item -> 'Pygmalio v03 c27-39 + Omake.zip - Pygmalio v03 c27-39 + Omake.zip'
Item -> 'Pygmalio v04 c40-53 + Omake.zip - Pygmalio v04 c40-53 + Omake.zip'
Item -> 'Pygmalio v05 c54-67 + Omake.zip - Pygmalio v05 c54-67 + Omake.zip'
Item -> 'Pygmalio v06 c68-80 + Omake.zip - Pygmalio v06 c68-80 + Omake.zip'
Item -> 'Pygmalio - 81 - pygmalio_81.zip'
Item -> 'Pygmalio - 82 - pygmalio_82.zip'
Item -> 'Pygmalio - 83 - pygmalio_83.zip'
Item -> 'Pygmalio - 84 - pygmalio_84.zip'
Item -> 'Pygmalio - 85 - pygmalio_85.zip'
Item -> 'Pygmalio - 86 - pygmalio_86.zip'
Item -> 'Pygmalio - v7 c87.zip'
Item -> 'Pygmalio - v7 c88.zip'
Item -> 'Pygmalio - c89 - 89.zip'
Item -> 'Pygmalio - v7 c89.zip'
Item -> 'Pygmalio - c90 - 90.zip'
Item -> 'Pygmalio - v7 c90.zip'
Item -> 'Pygmalio - c91 - 91.zip'
Item -> 'Pygmalio - v7 c91.zip'
Item -> 'Pygmalio - v7 c92.zip'
Item -> 'Pygmalio - v7 c93.zip'
Item -> 'Pygmalio - v8 c94.zip'
Item -> 'Pygmalio - v8 c95.zip'
Item -> 'Pygmalio - v8 c96.zip'
Item -> 'Pygmalio - v8 c97.zip'
Item -> 'Pygmalio v01[Wingtip Cafe].zip'
```

Note that there is room for choosing behaviour. Currently, my system ignores the volume number unless there is no chapter number in the filename. This works better when all files are sequentially ordered (chapter num increases monotonically). If chapter numbers are reset per-volume, sorting by volume in all cases is preferable (and what this pull request does).

Switching is simple enough, just set vol# to `0` if chap# > 0.