More natural grouping.

Make groups no shorter than 8 and no longer than 16 photos.
Also, make time and not only number of images a factor when
deciding which group to split next.
This commit is contained in:
Rasmus Kaj 2017-11-28 00:14:53 +01:00
parent 3071431452
commit 858f873f98
2 changed files with 44 additions and 33 deletions

View File

@ -48,31 +48,36 @@ pub struct PhotoLink {
impl PhotoLink {
fn for_group(g: &[Photo], base_url: &str) -> PhotoLink {
PhotoLink {
href: format!(
"{}?from={}&to={}",
base_url,
g.last().map(|p| p.id).unwrap_or(0),
g.first().map(|p| p.id).unwrap_or(0),
),
id: g.iter()
.max_by_key(|p| {
p.grade.unwrap_or(27) + if p.is_public { 38 } else { 0 }
})
.map(|p| p.id)
.unwrap_or(0),
lable: Some(format!(
"{} - {} ({})",
g.last()
.and_then(|p| p.date)
.map(|d| format!("{}", d.format("%F %T")))
.unwrap_or_else(|| "-".to_string()),
g.first()
.and_then(|p| p.date)
.map(|d| format!("{}", d.format("%F %T")))
.unwrap_or_else(|| "-".to_string()),
g.len(),
)),
if g.len() == 1 {
PhotoLink::from(&g[0])
} else {
fn imgscore(p: &Photo) -> i16 {
p.grade.unwrap_or(27) + if p.is_public { 38 } else { 0 }
}
PhotoLink {
href: format!(
"{}?from={}&to={}",
base_url,
g.last().map(|p| p.id).unwrap_or(0),
g.first().map(|p| p.id).unwrap_or(0),
),
id: g.iter()
.max_by_key(|ref p| imgscore(p))
.map(|ref p| p.id)
.unwrap_or(0),
lable: Some(format!(
"{} - {} ({})",
g.last()
.and_then(|p| p.date)
.map(|d| format!("{}", d.format("%F %T")))
.unwrap_or_else(|| "-".to_string()),
g.first()
.and_then(|p| p.date)
.map(|d| format!("{}", d.format("%F %T")))
.unwrap_or_else(|| "-".to_string()),
g.len(),
)),
}
}
}
}

View File

@ -36,10 +36,12 @@ pub fn links_by_time<'a>(
}
pub fn split_to_groups(photos: &[Photo]) -> Option<Vec<&[Photo]>> {
if photos.len() < 42 {
return None;
}
let wanted_groups = (photos.len() as f64).sqrt() as usize;
let wanted_groups = match photos.len() {
l if l <= 16 => return None,
l if l < 81 => 8,
l if l >= 225 => 15,
l => (l as f64).sqrt() as usize,
};
let mut groups = vec![&photos[..]];
while groups.len() < wanted_groups {
let i = find_largest(&groups);
@ -52,10 +54,13 @@ pub fn split_to_groups(photos: &[Photo]) -> Option<Vec<&[Photo]>> {
fn find_largest(groups: &[&[Photo]]) -> usize {
let mut found = 0;
let mut largest = 0;
let mut largest = 0.0;
for (i, g) in groups.iter().enumerate() {
if g.len() > largest {
largest = g.len();
let time = 1 + g.first().map(|p| timestamp(p)).unwrap_or(0)
- g.last().map(|p| timestamp(p)).unwrap_or(0);
let score = (g.len() as f64).powi(3) * (time as f64);
if score > largest {
largest = score;
found = i;
}
}
@ -64,9 +69,10 @@ fn find_largest(groups: &[&[Photo]]) -> usize {
fn split(group: &[Photo]) -> (&[Photo], &[Photo]) {
let l = group.len();
let edge = l / 16;
let mut pos = 0;
let mut dist = 0;
for i in l / 8..l - l / 8 - 1 {
for i in edge..l - 1 - edge {
let tttt = timestamp(&group[i]) - timestamp(&group[i + 1]);
if tttt > dist {
dist = tttt;