Class: Analysis::AnalyseModelFileJob

Inherits:
ApplicationJob
  • Object
show all
Defined in:
app/jobs/analysis/analyse_model_file_job.rb

Instance Method Summary collapse

Instance Method Details

#inefficiency_problem(file) ⇒ Object



75
76
77
78
79
80
81
82
# File 'app/jobs/analysis/analyse_model_file_job.rb', line 75

def inefficiency_problem(file)
  head = file.head(16)
  file.attachment_attacher.reload
  return "ASCII STL" if (file.extension === "stl") && (head.slice(0, 6) === "solid ")
  return "Wavefront OBJ" if file.extension === "obj"
  return "ASCII PLY" if (file.extension === "ply") && (head === "ply\rformat ascii")
  nil
end

#match_with_supported_file(file) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'app/jobs/analysis/analyse_model_file_job.rb', line 46

def match_with_supported_file(file)
  # If this is a supported file or already matched, don't do anything
  return if file.presupported || file.presupported_version
  # Otherwise, find presupported files in the same model
  # Build list of files with normalised names
  matches = file.model.model_files.presupported.select { |x| x.extension.downcase == file.extension.downcase }.map { |s|
    # Normalize filename
    human = s.name.humanize.downcase
    # Normalize name of this file
    normed = stopword_filter.filter(file.name.humanize.downcase.split)
    # Remove stop words
    human = stopword_filter.filter(human.split)
    # Measure distance from this filename
    d = String::Similarity.cosine(normed.join(" "), human.join(" "))
    [d, s]
  }.select { it[0] > 0.95 }
  best = case matches.length
  when 0
    nil
  when 1
    matches.first[1]
  else
    same_format = matches.select { it[1].mime_type === file.mime_type }
    matches = same_format unless same_format.empty?
    matches.max_by { it[0] }[1]
  end
  file.presupported_version = best
end

#perform(file_id) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'app/jobs/analysis/analyse_model_file_job.rb', line 7

def perform(file_id)
  file = ModelFile.find(file_id)
  # Don't run analysis if the file is missing
  # The Problem is raised elsewhere.
  return if !file.exists_on_storage?
  # If the file is modified, or we're lacking metadata
  status[:step] = "jobs.analysis.analyse_model_file.file_statistics" # i18n-tasks-use t('jobs.analysis.analyse_model_file.file_statistics')
  if file.file_last_modified > file.updated_at || file.digest.nil?
    # Store updated file metadata
    file.update!(digest: file.calculate_digest)
    # If the digest has changed, queue up detailed geometric mesh analysis
    file.analyse_geometry_later if file.is_3d_model? && file.digest_previously_changed?
  end
  # Raise problems for empty files
  Problem.create_or_clear file, :empty, (file.size == 0)
  status[:step] = "jobs.analysis.analyse_model_file.matching" # i18n-tasks-use t('jobs.analysis.analyse_model_file.matching')
  # Match supported files
  match_with_supported_file(file)
  status[:step] = "jobs.analysis.analyse_model_file.detect_ineffiency" # i18n-tasks-use t('jobs.analysis.analyse_model_file.detect_ineffiency')
  # Detect inefficient file formats
  message = inefficiency_problem(file)
  Problem.create_or_clear(
    file,
    :inefficient,
    !message.nil?,
    note: message
  )
  status[:step] = "jobs.analysis.analyse_model_file.detect_duplicates" # i18n-tasks-use t('jobs.analysis.analyse_model_file.detect_duplicates')
  # Detect duplicates
  Problem.create_or_clear(
    file,
    :duplicate,
    file.duplicate?
  )
  status[:step] = "jobs.analysis.analyse_model_file.generating_derivatives" # i18n-tasks-use t('jobs.analysis.analyse_model_file.generating_derivatives')
  # Check and update derivatives
  file.check_derivatives!
end